2012-12-04 10:59:38 +01:00
#!/usr/bin/env python
2013-10-15 12:05:13 +02:00
# coding: utf-8
2012-12-04 10:59:38 +01:00
2014-08-27 19:11:45 +02:00
from __future__ import unicode_literals
2013-10-15 02:00:53 +02:00
# Allow direct execution
import os
2012-11-27 23:20:29 +01:00
import sys
2012-09-28 14:47:01 +02:00
import unittest
2013-10-15 02:00:53 +02:00
sys . path . insert ( 0 , os . path . dirname ( os . path . dirname ( os . path . abspath ( __file__ ) ) ) )
2012-09-28 14:47:01 +02:00
2013-10-15 02:00:53 +02:00
# Various small unit tests
2014-02-25 01:43:17 +01:00
import io
2014-03-24 23:21:20 +01:00
import json
2013-10-15 02:00:53 +02:00
import xml . etree . ElementTree
2012-11-27 23:20:29 +01:00
2013-09-13 22:05:29 +02:00
from youtube_dl . utils import (
2015-01-07 07:20:20 +01:00
age_restricted ,
2014-12-14 21:59:59 +01:00
args_to_str ,
2016-02-27 03:19:50 +08:00
encode_base_n ,
2014-11-13 15:02:31 +01:00
clean_html ,
2019-08-25 14:22:51 -05:00
clean_html_markdown ,
2016-04-09 22:40:05 +02:00
date_from_str ,
2013-09-13 22:05:29 +02:00
DateRange ,
2014-12-14 21:59:59 +01:00
detect_exe_version ,
2015-11-22 06:33:52 +06:00
determine_ext ,
2016-02-07 06:12:53 +06:00
dict_get ,
2015-12-20 07:07:14 +06:00
encode_compat_str ,
2013-12-17 04:13:36 +01:00
encodeFilename ,
2014-12-14 21:59:59 +01:00
escape_rfc3986 ,
escape_url ,
2016-01-02 19:49:59 +00:00
extract_attributes ,
2015-03-21 14:12:43 +01:00
ExtractorError ,
2013-09-13 22:05:29 +02:00
find_xpath_attr ,
2014-01-20 22:11:34 +01:00
fix_xml_ampersands ,
2019-03-23 01:08:54 +07:00
float_or_none ,
2016-07-06 20:02:52 +08:00
get_element_by_class ,
2017-02-11 10:16:54 +01:00
get_element_by_attribute ,
get_elements_by_class ,
get_elements_by_attribute ,
2014-09-29 00:36:06 +02:00
InAdvancePagedList ,
2019-03-23 01:08:54 +07:00
int_or_none ,
2014-12-14 21:59:59 +01:00
intlist_to_bytes ,
2015-01-23 01:21:30 +01:00
is_html ,
2014-12-14 21:59:59 +01:00
js_to_json ,
limit_length ,
2018-04-28 02:47:17 +07:00
merge_dicts ,
2016-09-02 22:57:48 +07:00
mimetype2ext ,
2016-09-14 23:13:55 +07:00
month_by_name ,
2017-05-01 23:09:18 +08:00
multipart_encode ,
2016-02-17 06:01:44 +08:00
ohdave_rsa_encrypt ,
2014-12-14 21:59:59 +01:00
OnDemandPagedList ,
orderedSet ,
2016-08-07 20:45:18 +07:00
parse_age_limit ,
2013-12-26 13:49:44 +01:00
parse_duration ,
2014-12-14 21:59:59 +01:00
parse_filesize ,
2016-03-13 16:27:20 +06:00
parse_count ,
2014-12-14 21:59:59 +01:00
parse_iso8601 ,
2018-03-02 23:39:04 +07:00
parse_resolution ,
2019-03-17 09:07:47 +07:00
parse_bitrate ,
2017-02-27 18:50:19 +08:00
pkcs1pad ,
2014-02-25 01:43:17 +01:00
read_batch_urls ,
2013-12-17 04:13:36 +01:00
sanitize_filename ,
2015-03-08 20:55:22 +06:00
sanitize_path ,
2018-02-19 22:50:23 +07:00
sanitize_url ,
2017-03-26 02:30:10 +07:00
expand_path ,
2015-05-02 23:10:48 +06:00
prepend_extension ,
2015-05-02 23:23:06 +06:00
replace_extension ,
2016-05-19 04:31:30 +06:00
remove_start ,
remove_end ,
2015-12-14 21:30:58 +06:00
remove_quotes ,
2013-11-21 14:09:28 +01:00
shell_quote ,
2013-12-17 04:13:36 +01:00
smuggle_url ,
2013-12-06 13:36:36 +01:00
str_to_int ,
2014-12-14 21:59:59 +01:00
strip_jsonp ,
2019-05-23 23:58:35 +07:00
strip_or_none ,
2013-12-17 04:13:36 +01:00
timeconvert ,
unescapeHTML ,
unified_strdate ,
2016-06-25 22:30:35 +07:00
unified_timestamp ,
2013-12-17 04:13:36 +01:00
unsmuggle_url ,
2014-12-14 21:59:59 +01:00
uppercase_escape ,
2015-05-04 21:53:05 +08:00
lowercase_escape ,
2013-12-17 04:13:36 +01:00
url_basename ,
2018-07-21 18:01:06 +07:00
url_or_none ,
2016-11-02 02:14:01 +07:00
base_url ,
2016-12-13 02:23:49 +07:00
urljoin ,
2014-03-07 15:25:33 +01:00
urlencode_postdata ,
2016-06-26 15:16:49 +08:00
urshift ,
2016-03-03 18:40:05 +01:00
update_url_query ,
2014-12-06 12:14:26 +01:00
version_tuple ,
2014-12-14 21:59:59 +01:00
xpath_with_ns ,
2015-09-05 00:36:16 +06:00
xpath_element ,
2015-03-21 14:12:43 +01:00
xpath_text ,
2015-09-05 00:36:16 +06:00
xpath_attr ,
2015-01-25 02:38:47 +01:00
render_table ,
2015-02-10 03:32:21 +01:00
match_str ,
2015-04-25 23:15:05 +08:00
parse_dfxp_time_expr ,
dfxp2srt ,
2015-09-05 03:07:19 +06:00
cli_option ,
cli_valueless_option ,
cli_bool_option ,
2016-03-16 18:48:06 +01:00
parse_codecs ,
2013-09-13 22:05:29 +02:00
)
2015-10-25 20:04:55 +01:00
from youtube_dl . compat import (
2016-01-02 19:49:59 +00:00
compat_chr ,
2015-10-25 20:04:55 +01:00
compat_etree_fromstring ,
2017-03-26 02:30:10 +07:00
compat_getenv ,
2017-07-06 00:25:37 +07:00
compat_os_name ,
2017-03-26 02:30:10 +07:00
compat_setenv ,
2016-03-03 18:40:05 +01:00
compat_urlparse ,
compat_parse_qs ,
2015-10-25 20:04:55 +01:00
)
2012-09-28 14:47:01 +02:00
2012-11-28 12:59:27 +01:00
2012-09-28 14:47:01 +02:00
class TestUtil ( unittest . TestCase ) :
2012-11-28 02:04:46 +01:00
def test_timeconvert ( self ) :
self . assertTrue ( timeconvert ( ' ' ) is None )
self . assertTrue ( timeconvert ( ' bougrg ' ) is None )
def test_sanitize_filename ( self ) :
self . assertEqual ( sanitize_filename ( ' abc ' ) , ' abc ' )
self . assertEqual ( sanitize_filename ( ' abc_d-e ' ) , ' abc_d-e ' )
self . assertEqual ( sanitize_filename ( ' 123 ' ) , ' 123 ' )
self . assertEqual ( ' abc_de ' , sanitize_filename ( ' abc/de ' ) )
self . assertFalse ( ' / ' in sanitize_filename ( ' abc/de/// ' ) )
self . assertEqual ( ' abc_de ' , sanitize_filename ( ' abc/<> \\ *|de ' ) )
self . assertEqual ( ' xxx ' , sanitize_filename ( ' xxx/<> \\ *| ' ) )
self . assertEqual ( ' yes no ' , sanitize_filename ( ' yes? no ' ) )
self . assertEqual ( ' this - that ' , sanitize_filename ( ' this: that ' ) )
self . assertEqual ( sanitize_filename ( ' AT&T ' ) , ' AT&T ' )
2014-08-27 19:11:45 +02:00
aumlaut = ' ä '
2012-11-28 02:04:46 +01:00
self . assertEqual ( sanitize_filename ( aumlaut ) , aumlaut )
2014-08-27 19:11:45 +02:00
tests = ' \u043a \u0438 \u0440 \u0438 \u043b \u043b \u0438 \u0446 \u0430 '
2012-11-28 02:04:46 +01:00
self . assertEqual ( sanitize_filename ( tests ) , tests )
2015-01-11 17:40:45 +01:00
self . assertEqual (
sanitize_filename ( ' New World record at 0:12:34 ' ) ,
' New World record at 0_12_34 ' )
2015-03-02 19:07:17 +01:00
2015-02-24 11:38:01 +01:00
self . assertEqual ( sanitize_filename ( ' --gasdgf ' ) , ' _-gasdgf ' )
self . assertEqual ( sanitize_filename ( ' --gasdgf ' , is_id = True ) , ' --gasdgf ' )
2015-03-02 19:07:17 +01:00
self . assertEqual ( sanitize_filename ( ' .gasdgf ' ) , ' gasdgf ' )
self . assertEqual ( sanitize_filename ( ' .gasdgf ' , is_id = True ) , ' .gasdgf ' )
2015-01-11 17:40:45 +01:00
2012-11-28 02:04:46 +01:00
forbidden = ' " \0 \\ / '
for fc in forbidden :
for fbc in forbidden :
self . assertTrue ( fbc not in sanitize_filename ( fc ) )
def test_sanitize_filename_restricted ( self ) :
self . assertEqual ( sanitize_filename ( ' abc ' , restricted = True ) , ' abc ' )
self . assertEqual ( sanitize_filename ( ' abc_d-e ' , restricted = True ) , ' abc_d-e ' )
self . assertEqual ( sanitize_filename ( ' 123 ' , restricted = True ) , ' 123 ' )
self . assertEqual ( ' abc_de ' , sanitize_filename ( ' abc/de ' , restricted = True ) )
self . assertFalse ( ' / ' in sanitize_filename ( ' abc/de/// ' , restricted = True ) )
self . assertEqual ( ' abc_de ' , sanitize_filename ( ' abc/<> \\ *|de ' , restricted = True ) )
self . assertEqual ( ' xxx ' , sanitize_filename ( ' xxx/<> \\ *| ' , restricted = True ) )
self . assertEqual ( ' yes_no ' , sanitize_filename ( ' yes? no ' , restricted = True ) )
self . assertEqual ( ' this_-_that ' , sanitize_filename ( ' this: that ' , restricted = True ) )
2016-05-02 13:21:39 +10:00
tests = ' aäb \u4e2d \u56fd \u7684 c '
self . assertEqual ( sanitize_filename ( tests , restricted = True ) , ' aab_c ' )
2014-08-27 19:11:45 +02:00
self . assertTrue ( sanitize_filename ( ' \xf6 ' , restricted = True ) != ' ' ) # No empty filename
2012-11-28 02:04:46 +01:00
2012-11-28 12:59:27 +01:00
forbidden = ' " \0 \\ /&!: \' \t \n ()[] {} $;`^,# '
2012-11-28 02:04:46 +01:00
for fc in forbidden :
for fbc in forbidden :
self . assertTrue ( fbc not in sanitize_filename ( fc , restricted = True ) )
# Handle a common case more neatly
2014-08-27 19:11:45 +02:00
self . assertEqual ( sanitize_filename ( ' \u5927 \u58f0 \u5e26 - Song ' , restricted = True ) , ' Song ' )
self . assertEqual ( sanitize_filename ( ' \u603b \u7edf : Speech ' , restricted = True ) , ' Speech ' )
2012-11-28 02:04:46 +01:00
# .. but make sure the file name is never empty
self . assertTrue ( sanitize_filename ( ' - ' , restricted = True ) != ' ' )
self . assertTrue ( sanitize_filename ( ' : ' , restricted = True ) != ' ' )
2016-05-02 13:21:39 +10:00
self . assertEqual ( sanitize_filename (
2016-06-02 11:39:32 +02:00
' ÂÃÄÀÁÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖŐØŒÙÚÛÜŰÝÞßàáâãäåæçèéêëìíîïðñòóôõöőøœùúûüűýþÿ ' , restricted = True ) ,
2019-05-10 20:42:32 +02:00
' AAAAAAAECEEEEIIIIDNOOOOOOOOEUUUUUYTHssaaaaaaaeceeeeiiiionooooooooeuuuuuythy ' )
2016-05-02 13:21:39 +10:00
2012-12-03 15:36:24 +01:00
def test_sanitize_ids ( self ) :
2012-12-20 13:26:37 +01:00
self . assertEqual ( sanitize_filename ( ' _n_cd26wFpw ' , is_id = True ) , ' _n_cd26wFpw ' )
self . assertEqual ( sanitize_filename ( ' _BD_eEpuzXw ' , is_id = True ) , ' _BD_eEpuzXw ' )
self . assertEqual ( sanitize_filename ( ' N0Y__7-UOdI ' , is_id = True ) , ' N0Y__7-UOdI ' )
2012-12-03 15:36:24 +01:00
2015-03-08 20:55:22 +06:00
def test_sanitize_path ( self ) :
if sys . platform != ' win32 ' :
return
self . assertEqual ( sanitize_path ( ' abc ' ) , ' abc ' )
self . assertEqual ( sanitize_path ( ' abc/def ' ) , ' abc \\ def ' )
self . assertEqual ( sanitize_path ( ' abc \\ def ' ) , ' abc \\ def ' )
self . assertEqual ( sanitize_path ( ' abc|def ' ) , ' abc#def ' )
self . assertEqual ( sanitize_path ( ' <>: " |?* ' ) , ' ####### ' )
self . assertEqual ( sanitize_path ( ' C:/abc/def ' ) , ' C: \\ abc \\ def ' )
self . assertEqual ( sanitize_path ( ' C?:/abc/def ' ) , ' C## \\ abc \\ def ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ UNC \\ ComputerName \\ abc ' ) , ' \\ \\ ? \\ UNC \\ ComputerName \\ abc ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ UNC/ComputerName/abc ' ) , ' \\ \\ ? \\ UNC \\ ComputerName \\ abc ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ C: \\ abc ' ) , ' \\ \\ ? \\ C: \\ abc ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ C:/abc ' ) , ' \\ \\ ? \\ C: \\ abc ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ C: \\ ab?c \\ de:f ' ) , ' \\ \\ ? \\ C: \\ ab#c \\ de#f ' )
self . assertEqual ( sanitize_path ( ' \\ \\ ? \\ C: \\ abc ' ) , ' \\ \\ ? \\ C: \\ abc ' )
2015-03-08 22:08:48 +06:00
self . assertEqual (
sanitize_path ( ' youtube/ %(uploader)s / %(autonumber)s - %(title)s - %(upload_date)s . %(ext)s ' ) ,
' youtube \\ %(uploader)s \\ %(autonumber)s - %(title)s - %(upload_date)s . %(ext)s ' )
self . assertEqual (
sanitize_path ( ' youtube/TheWreckingYard ./00001-Not bad, Especially for Free! (1987 Yamaha 700)-20141116.mp4.part ' ) ,
' youtube \\ TheWreckingYard # \\ 00001-Not bad, Especially for Free! (1987 Yamaha 700)-20141116.mp4.part ' )
self . assertEqual ( sanitize_path ( ' abc/def... ' ) , ' abc \\ def..# ' )
self . assertEqual ( sanitize_path ( ' abc.../def ' ) , ' abc..# \\ def ' )
self . assertEqual ( sanitize_path ( ' abc.../def... ' ) , ' abc..# \\ def..# ' )
2015-03-10 00:50:11 +06:00
self . assertEqual ( sanitize_path ( ' ../abc ' ) , ' .. \\ abc ' )
self . assertEqual ( sanitize_path ( ' ../../abc ' ) , ' .. \\ .. \\ abc ' )
self . assertEqual ( sanitize_path ( ' ./abc ' ) , ' abc ' )
self . assertEqual ( sanitize_path ( ' ./../abc ' ) , ' .. \\ abc ' )
2018-02-19 22:50:23 +07:00
def test_sanitize_url ( self ) :
self . assertEqual ( sanitize_url ( ' //foo.bar ' ) , ' http://foo.bar ' )
self . assertEqual ( sanitize_url ( ' httpss://foo.bar ' ) , ' https://foo.bar ' )
self . assertEqual ( sanitize_url ( ' rmtps://foo.bar ' ) , ' rtmps://foo.bar ' )
self . assertEqual ( sanitize_url ( ' https://foo.bar ' ) , ' https://foo.bar ' )
2017-03-26 02:30:10 +07:00
def test_expand_path ( self ) :
2017-03-26 03:07:56 +07:00
def env ( var ) :
return ' % {0} % ' . format ( var ) if sys . platform == ' win32 ' else ' $ {0} ' . format ( var )
2017-03-26 03:22:48 +07:00
compat_setenv ( ' YOUTUBE_DL_EXPATH_PATH ' , ' expanded ' )
self . assertEqual ( expand_path ( env ( ' YOUTUBE_DL_EXPATH_PATH ' ) ) , ' expanded ' )
self . assertEqual ( expand_path ( env ( ' HOME ' ) ) , compat_getenv ( ' HOME ' ) )
2017-03-26 02:30:10 +07:00
self . assertEqual ( expand_path ( ' ~ ' ) , compat_getenv ( ' HOME ' ) )
2017-03-26 03:07:56 +07:00
self . assertEqual (
2017-03-26 03:22:48 +07:00
expand_path ( ' ~/ %s ' % env ( ' YOUTUBE_DL_EXPATH_PATH ' ) ) ,
2017-03-26 03:07:56 +07:00
' %s /expanded ' % compat_getenv ( ' HOME ' ) )
2017-03-26 02:30:10 +07:00
2015-05-02 23:10:48 +06:00
def test_prepend_extension ( self ) :
self . assertEqual ( prepend_extension ( ' abc.ext ' , ' temp ' ) , ' abc.temp.ext ' )
self . assertEqual ( prepend_extension ( ' abc.ext ' , ' temp ' , ' ext ' ) , ' abc.temp.ext ' )
self . assertEqual ( prepend_extension ( ' abc.unexpected_ext ' , ' temp ' , ' ext ' ) , ' abc.unexpected_ext.temp ' )
self . assertEqual ( prepend_extension ( ' abc ' , ' temp ' ) , ' abc.temp ' )
self . assertEqual ( prepend_extension ( ' .abc ' , ' temp ' ) , ' .abc.temp ' )
self . assertEqual ( prepend_extension ( ' .abc.ext ' , ' temp ' ) , ' .abc.temp.ext ' )
2015-05-02 23:23:06 +06:00
def test_replace_extension ( self ) :
self . assertEqual ( replace_extension ( ' abc.ext ' , ' temp ' ) , ' abc.temp ' )
self . assertEqual ( replace_extension ( ' abc.ext ' , ' temp ' , ' ext ' ) , ' abc.temp ' )
self . assertEqual ( replace_extension ( ' abc.unexpected_ext ' , ' temp ' , ' ext ' ) , ' abc.unexpected_ext.temp ' )
self . assertEqual ( replace_extension ( ' abc ' , ' temp ' ) , ' abc.temp ' )
self . assertEqual ( replace_extension ( ' .abc ' , ' temp ' ) , ' .abc.temp ' )
self . assertEqual ( replace_extension ( ' .abc.ext ' , ' temp ' ) , ' .abc.temp ' )
2016-05-19 04:31:30 +06:00
def test_remove_start ( self ) :
self . assertEqual ( remove_start ( None , ' A - ' ) , None )
self . assertEqual ( remove_start ( ' A - B ' , ' A - ' ) , ' B ' )
self . assertEqual ( remove_start ( ' B - A ' , ' A - ' ) , ' B - A ' )
def test_remove_end ( self ) :
self . assertEqual ( remove_end ( None , ' - B ' ) , None )
self . assertEqual ( remove_end ( ' A - B ' , ' - B ' ) , ' A ' )
self . assertEqual ( remove_end ( ' B - A ' , ' - B ' ) , ' B - A ' )
2015-12-14 21:30:58 +06:00
def test_remove_quotes ( self ) :
self . assertEqual ( remove_quotes ( None ) , None )
self . assertEqual ( remove_quotes ( ' " ' ) , ' " ' )
self . assertEqual ( remove_quotes ( " ' " ) , " ' " )
self . assertEqual ( remove_quotes ( ' ; ' ) , ' ; ' )
self . assertEqual ( remove_quotes ( ' " ; ' ) , ' " ; ' )
self . assertEqual ( remove_quotes ( ' " " ' ) , ' ' )
self . assertEqual ( remove_quotes ( ' " ; " ' ) , ' ; ' )
2012-11-28 02:04:46 +01:00
def test_ordered_set ( self ) :
2012-11-28 12:59:27 +01:00
self . assertEqual ( orderedSet ( [ 1 , 1 , 2 , 3 , 4 , 4 , 5 , 6 , 7 , 3 , 5 ] ) , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] )
2012-11-28 02:04:46 +01:00
self . assertEqual ( orderedSet ( [ ] ) , [ ] )
self . assertEqual ( orderedSet ( [ 1 ] ) , [ 1 ] )
2014-11-23 20:41:03 +01:00
# keep the list ordered
2012-11-28 12:59:27 +01:00
self . assertEqual ( orderedSet ( [ 135 , 1 , 1 , 1 ] ) , [ 135 , 1 ] )
2012-11-28 02:04:46 +01:00
def test_unescape_html ( self ) :
2014-08-27 19:11:45 +02:00
self . assertEqual ( unescapeHTML ( ' % 20; ' ) , ' % 20; ' )
2015-03-26 17:15:27 +02:00
self . assertEqual ( unescapeHTML ( ' / ' ) , ' / ' )
self . assertEqual ( unescapeHTML ( ' / ' ) , ' / ' )
2015-11-16 20:20:16 +06:00
self . assertEqual ( unescapeHTML ( ' é ' ) , ' é ' )
self . assertEqual ( unescapeHTML ( ' � ' ) , ' � ' )
2017-08-19 21:40:53 +08:00
self . assertEqual ( unescapeHTML ( ' &a" ' ) , ' &a " ' )
2016-06-10 15:11:55 +08:00
# HTML5 entities
self . assertEqual ( unescapeHTML ( ' .' ' ) , ' . \' ' )
2014-11-23 20:41:03 +01:00
2016-04-09 22:40:05 +02:00
def test_date_from_str ( self ) :
self . assertEqual ( date_from_str ( ' yesterday ' ) , date_from_str ( ' now-1day ' ) )
self . assertEqual ( date_from_str ( ' now+7day ' ) , date_from_str ( ' now+1week ' ) )
self . assertEqual ( date_from_str ( ' now+14day ' ) , date_from_str ( ' now+2week ' ) )
self . assertEqual ( date_from_str ( ' now+365day ' ) , date_from_str ( ' now+1year ' ) )
self . assertEqual ( date_from_str ( ' now+30day ' ) , date_from_str ( ' now+1month ' ) )
2013-04-27 14:01:55 +02:00
def test_daterange ( self ) :
2014-11-23 20:41:03 +01:00
_20century = DateRange ( " 19000101 " , " 20000101 " )
2013-04-27 14:01:55 +02:00
self . assertFalse ( " 17890714 " in _20century )
_ac = DateRange ( " 00010101 " )
self . assertTrue ( " 19690721 " in _ac )
_firstmilenium = DateRange ( end = " 10000101 " )
self . assertTrue ( " 07110427 " in _firstmilenium )
2013-04-28 11:39:37 +02:00
2013-04-27 15:14:20 +02:00
def test_unified_dates ( self ) :
self . assertEqual ( unified_strdate ( ' December 21, 2010 ' ) , ' 20101221 ' )
self . assertEqual ( unified_strdate ( ' 8/7/2009 ' ) , ' 20090708 ' )
self . assertEqual ( unified_strdate ( ' Dec 14, 2012 ' ) , ' 20121214 ' )
self . assertEqual ( unified_strdate ( ' 2012/10/11 01:56:38 +0000 ' ) , ' 20121011 ' )
2015-01-14 00:16:34 +02:00
self . assertEqual ( unified_strdate ( ' 1968 12 10 ' ) , ' 19681210 ' )
2014-02-09 18:09:57 +01:00
self . assertEqual ( unified_strdate ( ' 1968-12-10 ' ) , ' 19681210 ' )
2014-09-29 12:45:18 +02:00
self . assertEqual ( unified_strdate ( ' 28/01/2014 21:00:00 +0100 ' ) , ' 20140128 ' )
2014-12-12 02:57:36 +01:00
self . assertEqual (
unified_strdate ( ' 11/26/2014 11:30:00 AM PST ' , day_first = False ) ,
' 20141126 ' )
2015-02-03 10:58:28 +01:00
self . assertEqual (
unified_strdate ( ' 2/2/2015 6:47:40 PM ' , day_first = False ) ,
' 20150202 ' )
2016-02-25 00:52:49 +06:00
self . assertEqual ( unified_strdate ( ' Feb 14th 2016 5:45PM ' ) , ' 20160214 ' )
2015-04-04 19:11:01 +06:00
self . assertEqual ( unified_strdate ( ' 25-09-2014 ' ) , ' 20140925 ' )
2016-06-25 22:30:35 +07:00
self . assertEqual ( unified_strdate ( ' 27.02.2016 17:30 ' ) , ' 20160227 ' )
2015-11-02 14:08:38 +01:00
self . assertEqual ( unified_strdate ( ' UNKNOWN DATE FORMAT ' ) , None )
2016-09-29 23:47:25 +07:00
self . assertEqual ( unified_strdate ( ' Feb 7, 2016 at 6:35 pm ' ) , ' 20160207 ' )
2017-01-12 22:39:45 +07:00
self . assertEqual ( unified_strdate ( ' July 15th, 2013 ' ) , ' 20130715 ' )
self . assertEqual ( unified_strdate ( ' September 1st, 2013 ' ) , ' 20130901 ' )
self . assertEqual ( unified_strdate ( ' Sep 2nd, 2013 ' ) , ' 20130902 ' )
2012-11-27 23:20:29 +01:00
2016-06-25 22:30:35 +07:00
def test_unified_timestamps ( self ) :
self . assertEqual ( unified_timestamp ( ' December 21, 2010 ' ) , 1292889600 )
self . assertEqual ( unified_timestamp ( ' 8/7/2009 ' ) , 1247011200 )
self . assertEqual ( unified_timestamp ( ' Dec 14, 2012 ' ) , 1355443200 )
self . assertEqual ( unified_timestamp ( ' 2012/10/11 01:56:38 +0000 ' ) , 1349920598 )
self . assertEqual ( unified_timestamp ( ' 1968 12 10 ' ) , - 33436800 )
self . assertEqual ( unified_timestamp ( ' 1968-12-10 ' ) , - 33436800 )
self . assertEqual ( unified_timestamp ( ' 28/01/2014 21:00:00 +0100 ' ) , 1390939200 )
self . assertEqual (
unified_timestamp ( ' 11/26/2014 11:30:00 AM PST ' , day_first = False ) ,
1417001400 )
self . assertEqual (
unified_timestamp ( ' 2/2/2015 6:47:40 PM ' , day_first = False ) ,
1422902860 )
self . assertEqual ( unified_timestamp ( ' Feb 14th 2016 5:45PM ' ) , 1455471900 )
self . assertEqual ( unified_timestamp ( ' 25-09-2014 ' ) , 1411603200 )
self . assertEqual ( unified_timestamp ( ' 27.02.2016 17:30 ' ) , 1456594200 )
self . assertEqual ( unified_timestamp ( ' UNKNOWN DATE FORMAT ' ) , None )
2016-08-05 11:41:55 +08:00
self . assertEqual ( unified_timestamp ( ' May 16, 2016 11:15 PM ' ) , 1463440500 )
2016-09-29 23:47:25 +07:00
self . assertEqual ( unified_timestamp ( ' Feb 7, 2016 at 6:35 pm ' ) , 1454870100 )
2017-04-30 21:07:30 +07:00
self . assertEqual ( unified_timestamp ( ' 2017-03-30T17:52:41Q ' ) , 1490896361 )
2017-06-11 21:27:22 +07:00
self . assertEqual ( unified_timestamp ( ' Sep 11, 2013 | 5:49 AM ' ) , 1378878540 )
2017-12-16 21:56:16 +07:00
self . assertEqual ( unified_timestamp ( ' December 15, 2017 at 7:49 am ' ) , 1513324140 )
2018-03-14 01:28:40 +01:00
self . assertEqual ( unified_timestamp ( ' 2018-03-14T08:32:43.1493874+00:00 ' ) , 1521016363 )
2016-06-25 22:30:35 +07:00
2015-11-22 06:33:52 +06:00
def test_determine_ext ( self ) :
self . assertEqual ( determine_ext ( ' http://example.com/foo/bar.mp4/?download ' ) , ' mp4 ' )
self . assertEqual ( determine_ext ( ' http://example.com/foo/bar/?download ' , None ) , None )
2015-11-22 17:27:13 +06:00
self . assertEqual ( determine_ext ( ' http://example.com/foo/bar.nonext/?download ' , None ) , None )
self . assertEqual ( determine_ext ( ' http://example.com/foo/bar/mp4?download ' , None ) , None )
self . assertEqual ( determine_ext ( ' http://example.com/foo/bar.m3u8//?download ' ) , ' m3u8 ' )
2018-06-01 20:16:22 +03:00
self . assertEqual ( determine_ext ( ' foobar ' , None ) , None )
2015-11-22 06:33:52 +06:00
2013-07-11 16:12:08 +02:00
def test_find_xpath_attr ( self ) :
2014-08-27 19:11:45 +02:00
testxml = ''' <root>
2013-07-11 16:12:08 +02:00
< node / >
< node x = " a " / >
< node x = " a " y = " c " / >
< node x = " b " y = " d " / >
2015-08-01 20:22:13 +06:00
< node x = " " / >
2013-07-11 16:12:08 +02:00
< / root > '''
2015-10-25 20:04:55 +01:00
doc = compat_etree_fromstring ( testxml )
2013-07-11 16:12:08 +02:00
2015-08-01 20:22:13 +06:00
self . assertEqual ( find_xpath_attr ( doc , ' .//fourohfour ' , ' n ' ) , None )
2013-07-11 16:12:08 +02:00
self . assertEqual ( find_xpath_attr ( doc , ' .//fourohfour ' , ' n ' , ' v ' ) , None )
2015-08-01 20:22:13 +06:00
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' n ' ) , None )
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' n ' , ' v ' ) , None )
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' x ' ) , doc [ 1 ] )
2013-07-11 16:12:08 +02:00
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' x ' , ' a ' ) , doc [ 1 ] )
2015-08-01 20:22:13 +06:00
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' x ' , ' b ' ) , doc [ 3 ] )
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' y ' ) , doc [ 2 ] )
2013-07-11 16:12:08 +02:00
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' y ' , ' c ' ) , doc [ 2 ] )
2015-08-01 20:22:13 +06:00
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' y ' , ' d ' ) , doc [ 3 ] )
self . assertEqual ( find_xpath_attr ( doc , ' .//node ' , ' x ' , ' ' ) , doc [ 4 ] )
2013-07-11 16:12:08 +02:00
2013-10-12 21:34:04 +02:00
def test_xpath_with_ns ( self ) :
2014-08-27 19:11:45 +02:00
testxml = ''' <root xmlns:media= " http://example.com/ " >
2013-10-12 21:34:04 +02:00
< media : song >
< media : author > The Author < / media : author >
< url > http : / / server . com / download . mp3 < / url >
< / media : song >
< / root > '''
2015-10-25 20:04:55 +01:00
doc = compat_etree_fromstring ( testxml )
2013-10-12 21:34:04 +02:00
find = lambda p : doc . find ( xpath_with_ns ( p , { ' media ' : ' http://example.com/ ' } ) )
self . assertTrue ( find ( ' media:song ' ) is not None )
2014-08-27 19:11:45 +02:00
self . assertEqual ( find ( ' media:song/media:author ' ) . text , ' The Author ' )
self . assertEqual ( find ( ' media:song/url ' ) . text , ' http://server.com/download.mp3 ' )
2013-10-12 21:34:04 +02:00
2015-09-05 00:36:16 +06:00
def test_xpath_element ( self ) :
doc = xml . etree . ElementTree . Element ( ' root ' )
div = xml . etree . ElementTree . SubElement ( doc , ' div ' )
p = xml . etree . ElementTree . SubElement ( div , ' p ' )
p . text = ' Foo '
self . assertEqual ( xpath_element ( doc , ' div/p ' ) , p )
2015-10-31 22:39:44 +06:00
self . assertEqual ( xpath_element ( doc , [ ' div/p ' ] ) , p )
self . assertEqual ( xpath_element ( doc , [ ' div/bar ' , ' div/p ' ] ) , p )
2015-09-05 00:36:16 +06:00
self . assertEqual ( xpath_element ( doc , ' div/bar ' , default = ' default ' ) , ' default ' )
2015-10-31 22:39:44 +06:00
self . assertEqual ( xpath_element ( doc , [ ' div/bar ' ] , default = ' default ' ) , ' default ' )
2015-09-05 00:36:16 +06:00
self . assertTrue ( xpath_element ( doc , ' div/bar ' ) is None )
2015-10-31 22:39:44 +06:00
self . assertTrue ( xpath_element ( doc , [ ' div/bar ' ] ) is None )
self . assertTrue ( xpath_element ( doc , [ ' div/bar ' ] , ' div/baz ' ) is None )
2015-09-05 00:36:16 +06:00
self . assertRaises ( ExtractorError , xpath_element , doc , ' div/bar ' , fatal = True )
2015-10-31 22:39:44 +06:00
self . assertRaises ( ExtractorError , xpath_element , doc , [ ' div/bar ' ] , fatal = True )
self . assertRaises ( ExtractorError , xpath_element , doc , [ ' div/bar ' , ' div/baz ' ] , fatal = True )
2015-09-05 00:36:16 +06:00
2015-03-21 14:12:43 +01:00
def test_xpath_text ( self ) :
testxml = ''' <root>
< div >
< p > Foo < / p >
< / div >
< / root > '''
2015-10-25 20:04:55 +01:00
doc = compat_etree_fromstring ( testxml )
2015-03-21 14:12:43 +01:00
self . assertEqual ( xpath_text ( doc , ' div/p ' ) , ' Foo ' )
2015-09-05 00:36:16 +06:00
self . assertEqual ( xpath_text ( doc , ' div/bar ' , default = ' default ' ) , ' default ' )
2015-03-21 14:12:43 +01:00
self . assertTrue ( xpath_text ( doc , ' div/bar ' ) is None )
self . assertRaises ( ExtractorError , xpath_text , doc , ' div/bar ' , fatal = True )
2015-09-05 00:36:16 +06:00
def test_xpath_attr ( self ) :
testxml = ''' <root>
< div >
< p x = " a " > Foo < / p >
< / div >
< / root > '''
2015-10-25 20:04:55 +01:00
doc = compat_etree_fromstring ( testxml )
2015-09-05 00:36:16 +06:00
self . assertEqual ( xpath_attr ( doc , ' div/p ' , ' x ' ) , ' a ' )
self . assertEqual ( xpath_attr ( doc , ' div/bar ' , ' x ' ) , None )
self . assertEqual ( xpath_attr ( doc , ' div/p ' , ' y ' ) , None )
self . assertEqual ( xpath_attr ( doc , ' div/bar ' , ' x ' , default = ' default ' ) , ' default ' )
self . assertEqual ( xpath_attr ( doc , ' div/p ' , ' y ' , default = ' default ' ) , ' default ' )
self . assertRaises ( ExtractorError , xpath_attr , doc , ' div/bar ' , ' x ' , fatal = True )
self . assertRaises ( ExtractorError , xpath_attr , doc , ' div/p ' , ' y ' , fatal = True )
2013-10-15 12:05:13 +02:00
def test_smuggle_url ( self ) :
2014-11-26 13:07:32 +01:00
data = { " ö " : " ö " , " abc " : [ 3 ] }
2013-10-15 12:05:13 +02:00
url = ' https://foo.bar/baz?x=y#a '
smug_url = smuggle_url ( url , data )
unsmug_url , unsmug_data = unsmuggle_url ( smug_url )
self . assertEqual ( url , unsmug_url )
self . assertEqual ( data , unsmug_data )
res_url , res_data = unsmuggle_url ( url )
self . assertEqual ( res_url , url )
self . assertEqual ( res_data , None )
2016-07-04 21:36:32 +01:00
smug_url = smuggle_url ( url , { ' a ' : ' b ' } )
smug_smug_url = smuggle_url ( smug_url , { ' c ' : ' d ' } )
res_url , res_data = unsmuggle_url ( smug_smug_url )
self . assertEqual ( res_url , url )
self . assertEqual ( res_data , { ' a ' : ' b ' , ' c ' : ' d ' } )
2013-11-21 14:09:28 +01:00
def test_shell_quote ( self ) :
2014-08-27 19:11:45 +02:00
args = [ ' ffmpeg ' , ' -i ' , encodeFilename ( ' ñ€ß \' .mp4 ' ) ]
2017-07-06 00:25:37 +07:00
self . assertEqual (
shell_quote ( args ) ,
""" ffmpeg -i ' ñ€ß ' " ' " ' .mp4 ' """ if compat_os_name != ' nt ' else ''' ffmpeg -i " ñ€ß ' .mp4 " ''' )
2013-11-21 14:09:28 +01:00
2019-03-23 01:08:54 +07:00
def test_float_or_none ( self ) :
self . assertEqual ( float_or_none ( ' 42.42 ' ) , 42.42 )
self . assertEqual ( float_or_none ( ' 42 ' ) , 42.0 )
self . assertEqual ( float_or_none ( ' ' ) , None )
self . assertEqual ( float_or_none ( None ) , None )
self . assertEqual ( float_or_none ( [ ] ) , None )
self . assertEqual ( float_or_none ( set ( ) ) , None )
def test_int_or_none ( self ) :
self . assertEqual ( int_or_none ( ' 42 ' ) , 42 )
self . assertEqual ( int_or_none ( ' ' ) , None )
self . assertEqual ( int_or_none ( None ) , None )
self . assertEqual ( int_or_none ( [ ] ) , None )
self . assertEqual ( int_or_none ( set ( ) ) , None )
2013-12-06 13:36:36 +01:00
def test_str_to_int ( self ) :
self . assertEqual ( str_to_int ( ' 123,456 ' ) , 123456 )
self . assertEqual ( str_to_int ( ' 123.456 ' ) , 123456 )
2013-12-17 04:13:36 +01:00
def test_url_basename ( self ) :
2014-08-27 19:11:45 +02:00
self . assertEqual ( url_basename ( ' http://foo.de/ ' ) , ' ' )
self . assertEqual ( url_basename ( ' http://foo.de/bar/baz ' ) , ' baz ' )
self . assertEqual ( url_basename ( ' http://foo.de/bar/baz?x=y ' ) , ' baz ' )
self . assertEqual ( url_basename ( ' http://foo.de/bar/baz#x=y ' ) , ' baz ' )
self . assertEqual ( url_basename ( ' http://foo.de/bar/baz/ ' ) , ' baz ' )
2013-12-17 12:32:58 +01:00
self . assertEqual (
2014-08-27 19:11:45 +02:00
url_basename ( ' http://media.w3.org/2010/05/sintel/trailer.mp4 ' ) ,
' trailer.mp4 ' )
2013-10-15 12:05:13 +02:00
2016-11-02 02:14:01 +07:00
def test_base_url ( self ) :
self . assertEqual ( base_url ( ' http://foo.de/ ' ) , ' http://foo.de/ ' )
self . assertEqual ( base_url ( ' http://foo.de/bar ' ) , ' http://foo.de/ ' )
self . assertEqual ( base_url ( ' http://foo.de/bar/ ' ) , ' http://foo.de/bar/ ' )
self . assertEqual ( base_url ( ' http://foo.de/bar/baz ' ) , ' http://foo.de/bar/ ' )
self . assertEqual ( base_url ( ' http://foo.de/bar/baz?x=z/x/c ' ) , ' http://foo.de/bar/ ' )
2016-12-13 02:23:49 +07:00
def test_urljoin ( self ) :
self . assertEqual ( urljoin ( ' http://foo.de/ ' , ' /a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
2017-03-06 03:57:46 +07:00
self . assertEqual ( urljoin ( b ' http://foo.de/ ' , ' /a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( ' http://foo.de/ ' , b ' /a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( b ' http://foo.de/ ' , b ' /a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
2016-12-17 18:44:53 +07:00
self . assertEqual ( urljoin ( ' //foo.de/ ' , ' /a/b/c.txt ' ) , ' //foo.de/a/b/c.txt ' )
2016-12-13 02:23:49 +07:00
self . assertEqual ( urljoin ( ' http://foo.de/ ' , ' a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( ' http://foo.de ' , ' /a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( ' http://foo.de ' , ' a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( ' http://foo.de/ ' , ' http://foo.de/a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
2016-12-17 18:44:53 +07:00
self . assertEqual ( urljoin ( ' http://foo.de/ ' , ' //foo.de/a/b/c.txt ' ) , ' //foo.de/a/b/c.txt ' )
2016-12-13 02:23:49 +07:00
self . assertEqual ( urljoin ( None , ' http://foo.de/a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
2016-12-17 18:44:53 +07:00
self . assertEqual ( urljoin ( None , ' //foo.de/a/b/c.txt ' ) , ' //foo.de/a/b/c.txt ' )
2016-12-13 02:23:49 +07:00
self . assertEqual ( urljoin ( ' ' , ' http://foo.de/a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( [ ' foobar ' ] , ' http://foo.de/a/b/c.txt ' ) , ' http://foo.de/a/b/c.txt ' )
self . assertEqual ( urljoin ( ' http://foo.de/ ' , None ) , None )
self . assertEqual ( urljoin ( ' http://foo.de/ ' , ' ' ) , None )
self . assertEqual ( urljoin ( ' http://foo.de/ ' , [ ' foobar ' ] ) , None )
2016-12-20 12:23:16 +01:00
self . assertEqual ( urljoin ( ' http://foo.de/a/b/c.txt ' , ' .././../d.txt ' ) , ' http://foo.de/d.txt ' )
2019-01-20 20:21:24 +07:00
self . assertEqual ( urljoin ( ' http://foo.de/a/b/c.txt ' , ' rtmp://foo.de ' ) , ' rtmp://foo.de ' )
self . assertEqual ( urljoin ( None , ' rtmp://foo.de ' ) , ' rtmp://foo.de ' )
2016-12-13 02:23:49 +07:00
2018-07-21 18:01:06 +07:00
def test_url_or_none ( self ) :
self . assertEqual ( url_or_none ( None ) , None )
self . assertEqual ( url_or_none ( ' ' ) , None )
self . assertEqual ( url_or_none ( ' foo ' ) , None )
self . assertEqual ( url_or_none ( ' http://foo.de ' ) , ' http://foo.de ' )
self . assertEqual ( url_or_none ( ' https://foo.de ' ) , ' https://foo.de ' )
self . assertEqual ( url_or_none ( ' http$://foo.de ' ) , None )
self . assertEqual ( url_or_none ( ' http://foo.de ' ) , ' http://foo.de ' )
self . assertEqual ( url_or_none ( ' //foo.de ' ) , ' //foo.de ' )
2016-08-07 20:45:18 +07:00
def test_parse_age_limit ( self ) :
self . assertEqual ( parse_age_limit ( None ) , None )
self . assertEqual ( parse_age_limit ( False ) , None )
self . assertEqual ( parse_age_limit ( ' invalid ' ) , None )
self . assertEqual ( parse_age_limit ( 0 ) , 0 )
self . assertEqual ( parse_age_limit ( 18 ) , 18 )
self . assertEqual ( parse_age_limit ( 21 ) , 21 )
self . assertEqual ( parse_age_limit ( 22 ) , None )
self . assertEqual ( parse_age_limit ( ' 18 ' ) , 18 )
self . assertEqual ( parse_age_limit ( ' 18+ ' ) , 18 )
self . assertEqual ( parse_age_limit ( ' PG-13 ' ) , 13 )
self . assertEqual ( parse_age_limit ( ' TV-14 ' ) , 14 )
self . assertEqual ( parse_age_limit ( ' TV-MA ' ) , 17 )
2018-05-23 12:20:05 +01:00
self . assertEqual ( parse_age_limit ( ' TV14 ' ) , 14 )
self . assertEqual ( parse_age_limit ( ' TV_G ' ) , 0 )
2016-08-07 20:45:18 +07:00
2013-12-26 13:49:44 +01:00
def test_parse_duration ( self ) :
self . assertEqual ( parse_duration ( None ) , None )
2015-01-12 21:39:58 +06:00
self . assertEqual ( parse_duration ( False ) , None )
self . assertEqual ( parse_duration ( ' invalid ' ) , None )
2013-12-26 13:49:44 +01:00
self . assertEqual ( parse_duration ( ' 1 ' ) , 1 )
self . assertEqual ( parse_duration ( ' 1337:12 ' ) , 80232 )
self . assertEqual ( parse_duration ( ' 9:12:43 ' ) , 33163 )
2014-02-17 03:46:26 +07:00
self . assertEqual ( parse_duration ( ' 12:00 ' ) , 720 )
self . assertEqual ( parse_duration ( ' 00:01:01 ' ) , 61 )
2013-12-26 13:49:44 +01:00
self . assertEqual ( parse_duration ( ' x:y ' ) , None )
2014-02-17 03:46:26 +07:00
self . assertEqual ( parse_duration ( ' 3h11m53s ' ) , 11513 )
2014-08-31 06:41:30 +07:00
self . assertEqual ( parse_duration ( ' 3h 11m 53s ' ) , 11513 )
self . assertEqual ( parse_duration ( ' 3 hours 11 minutes 53 seconds ' ) , 11513 )
self . assertEqual ( parse_duration ( ' 3 hours 11 mins 53 secs ' ) , 11513 )
2014-02-17 03:46:26 +07:00
self . assertEqual ( parse_duration ( ' 62m45s ' ) , 3765 )
self . assertEqual ( parse_duration ( ' 6m59s ' ) , 419 )
self . assertEqual ( parse_duration ( ' 49s ' ) , 49 )
self . assertEqual ( parse_duration ( ' 0h0m0s ' ) , 0 )
self . assertEqual ( parse_duration ( ' 0m0s ' ) , 0 )
self . assertEqual ( parse_duration ( ' 0s ' ) , 0 )
2014-08-25 12:59:53 +02:00
self . assertEqual ( parse_duration ( ' 01:02:03.05 ' ) , 3723.05 )
2014-11-16 14:55:22 +01:00
self . assertEqual ( parse_duration ( ' T30M38S ' ) , 1838 )
2014-12-04 17:35:40 +01:00
self . assertEqual ( parse_duration ( ' 5 s ' ) , 5 )
self . assertEqual ( parse_duration ( ' 3 min ' ) , 180 )
self . assertEqual ( parse_duration ( ' 2.5 hours ' ) , 9000 )
2015-02-02 21:48:54 +01:00
self . assertEqual ( parse_duration ( ' 02:03:04 ' ) , 7384 )
self . assertEqual ( parse_duration ( ' 01:02:03:04 ' ) , 93784 )
2015-02-26 01:25:00 +01:00
self . assertEqual ( parse_duration ( ' 1 hour 3 minutes ' ) , 3780 )
2015-07-22 23:15:22 +08:00
self . assertEqual ( parse_duration ( ' 87 Min. ' ) , 5220 )
2016-04-07 19:30:47 +01:00
self . assertEqual ( parse_duration ( ' PT1H0.040S ' ) , 3600.04 )
2017-01-26 23:23:08 +07:00
self . assertEqual ( parse_duration ( ' PT00H03M30SZ ' ) , 210 )
2017-10-29 07:04:48 +07:00
self . assertEqual ( parse_duration ( ' P0Y0M0DT0H4M20.880S ' ) , 260.88 )
2013-12-26 13:49:44 +01:00
2014-01-20 22:11:34 +01:00
def test_fix_xml_ampersands ( self ) :
self . assertEqual (
fix_xml_ampersands ( ' " &x=y&z=a ' ) , ' " &x=y&z=a ' )
self . assertEqual (
fix_xml_ampersands ( ' " &x=y&wrong;&z=a ' ) ,
' " &x=y&wrong;&z=a ' )
self . assertEqual (
fix_xml_ampersands ( ' &'><" ' ) ,
' &'><" ' )
self . assertEqual (
fix_xml_ampersands ( ' Ӓ᪼ ' ) , ' Ӓ᪼ ' )
self . assertEqual ( fix_xml_ampersands ( ' &#&# ' ) , ' &#&# ' )
2014-01-20 11:36:47 +01:00
def test_paged_list ( self ) :
def testPL ( size , pagesize , sliceargs , expected ) :
def get_page ( pagenum ) :
firstid = pagenum * pagesize
upto = min ( size , pagenum * pagesize + pagesize )
for i in range ( firstid , upto ) :
yield i
2014-09-29 00:36:06 +02:00
pl = OnDemandPagedList ( get_page , pagesize )
2014-01-20 11:36:47 +01:00
got = pl . getslice ( * sliceargs )
self . assertEqual ( got , expected )
2014-09-29 00:36:06 +02:00
iapl = InAdvancePagedList ( get_page , size / / pagesize + 1 , pagesize )
got = iapl . getslice ( * sliceargs )
self . assertEqual ( got , expected )
2014-01-20 11:36:47 +01:00
testPL ( 5 , 2 , ( ) , [ 0 , 1 , 2 , 3 , 4 ] )
testPL ( 5 , 2 , ( 1 , ) , [ 1 , 2 , 3 , 4 ] )
testPL ( 5 , 2 , ( 2 , ) , [ 2 , 3 , 4 ] )
testPL ( 5 , 2 , ( 4 , ) , [ 4 ] )
testPL ( 5 , 2 , ( 0 , 3 ) , [ 0 , 1 , 2 ] )
testPL ( 5 , 2 , ( 1 , 4 ) , [ 1 , 2 , 3 ] )
testPL ( 5 , 2 , ( 2 , 99 ) , [ 2 , 3 , 4 ] )
testPL ( 5 , 2 , ( 20 , 99 ) , [ ] )
2014-02-25 01:43:17 +01:00
def test_read_batch_urls ( self ) :
2014-08-27 19:11:45 +02:00
f = io . StringIO ( ''' \xef \xbb \xbf foo
2014-02-25 01:43:17 +01:00
bar \r
baz
# More after this line\r
; or after this
bam ''' )
2014-08-27 19:11:45 +02:00
self . assertEqual ( read_batch_urls ( f ) , [ ' foo ' , ' bar ' , ' baz ' , ' bam ' ] )
2014-02-25 01:43:17 +01:00
2014-03-07 15:25:33 +01:00
def test_urlencode_postdata ( self ) :
data = urlencode_postdata ( { ' username ' : ' foo@bar.com ' , ' password ' : ' 1234 ' } )
self . assertTrue ( isinstance ( data , bytes ) )
2016-03-03 18:40:05 +01:00
def test_update_url_query ( self ) :
def query_dict ( url ) :
return compat_parse_qs ( compat_urlparse . urlparse ( url ) . query )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' quality ' : [ ' HD ' ] , ' format ' : [ ' mp4 ' ] } ) ) ,
query_dict ( ' http://example.com/path?quality=HD&format=mp4 ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' system ' : [ ' LINUX ' , ' WINDOWS ' ] } ) ) ,
query_dict ( ' http://example.com/path?system=LINUX&system=WINDOWS ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' fields ' : ' id,formats,subtitles ' } ) ) ,
query_dict ( ' http://example.com/path?fields=id,formats,subtitles ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' fields ' : ( ' id,formats,subtitles ' , ' thumbnails ' ) } ) ) ,
query_dict ( ' http://example.com/path?fields=id,formats,subtitles&fields=thumbnails ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path?manifest=f4m ' , { ' manifest ' : [ ] } ) ) ,
query_dict ( ' http://example.com/path ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path?system=LINUX&system=WINDOWS ' , { ' system ' : ' LINUX ' } ) ) ,
query_dict ( ' http://example.com/path?system=LINUX ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' fields ' : b ' id,formats,subtitles ' } ) ) ,
query_dict ( ' http://example.com/path?fields=id,formats,subtitles ' ) )
2016-03-03 19:18:57 +01:00
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' width ' : 1080 , ' height ' : 720 } ) ) ,
query_dict ( ' http://example.com/path?width=1080&height=720 ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' bitrate ' : 5020.43 } ) ) ,
query_dict ( ' http://example.com/path?bitrate=5020.43 ' ) )
self . assertEqual ( query_dict ( update_url_query (
' http://example.com/path ' , { ' test ' : ' 第二行тест ' } ) ) ,
query_dict ( ' http://example.com/path?test= %E 7 % AC % AC %E 4 % BA % 8C %E 8 % A1 % 8C % D1 %82% D0 % B5 % D1 %81% D1 % 82 ' ) )
2016-03-03 18:40:05 +01:00
2017-05-01 23:09:18 +08:00
def test_multipart_encode ( self ) :
self . assertEqual (
multipart_encode ( { b ' field ' : b ' value ' } , boundary = ' AAAAAA ' ) [ 0 ] ,
b ' --AAAAAA \r \n Content-Disposition: form-data; name= " field " \r \n \r \n value \r \n --AAAAAA-- \r \n ' )
self . assertEqual (
multipart_encode ( { ' 欄位 ' . encode ( ' utf-8 ' ) : ' 值 ' . encode ( ' utf-8 ' ) } , boundary = ' AAAAAA ' ) [ 0 ] ,
b ' --AAAAAA \r \n Content-Disposition: form-data; name= " \xe6 \xac \x84 \xe4 \xbd \x8d " \r \n \r \n \xe5 \x80 \xbc \r \n --AAAAAA-- \r \n ' )
self . assertRaises (
ValueError , multipart_encode , { b ' field ' : b ' value ' } , boundary = ' value ' )
2016-02-07 06:12:53 +06:00
def test_dict_get ( self ) :
2016-02-07 08:13:04 +06:00
FALSE_VALUES = {
' none ' : None ,
' false ' : False ,
' zero ' : 0 ,
' empty_string ' : ' ' ,
' empty_list ' : [ ] ,
2016-02-07 06:12:53 +06:00
}
2016-02-07 08:13:04 +06:00
d = FALSE_VALUES . copy ( )
d [ ' a ' ] = 42
2016-02-07 06:12:53 +06:00
self . assertEqual ( dict_get ( d , ' a ' ) , 42 )
self . assertEqual ( dict_get ( d , ' b ' ) , None )
self . assertEqual ( dict_get ( d , ' b ' , 42 ) , 42 )
self . assertEqual ( dict_get ( d , ( ' a ' , ) ) , 42 )
self . assertEqual ( dict_get ( d , ( ' b ' , ' a ' , ) ) , 42 )
self . assertEqual ( dict_get ( d , ( ' b ' , ' c ' , ' a ' , ' d ' , ) ) , 42 )
self . assertEqual ( dict_get ( d , ( ' b ' , ' c ' , ) ) , None )
self . assertEqual ( dict_get ( d , ( ' b ' , ' c ' , ) , 42 ) , 42 )
2016-02-07 08:13:04 +06:00
for key , false_value in FALSE_VALUES . items ( ) :
self . assertEqual ( dict_get ( d , ( ' b ' , ' c ' , key , ) ) , None )
self . assertEqual ( dict_get ( d , ( ' b ' , ' c ' , key , ) , skip_false_values = False ) , false_value )
2016-02-07 06:12:53 +06:00
2018-04-28 02:47:17 +07:00
def test_merge_dicts ( self ) :
self . assertEqual ( merge_dicts ( { ' a ' : 1 } , { ' b ' : 2 } ) , { ' a ' : 1 , ' b ' : 2 } )
self . assertEqual ( merge_dicts ( { ' a ' : 1 } , { ' a ' : 2 } ) , { ' a ' : 1 } )
self . assertEqual ( merge_dicts ( { ' a ' : 1 } , { ' a ' : None } ) , { ' a ' : 1 } )
self . assertEqual ( merge_dicts ( { ' a ' : 1 } , { ' a ' : ' ' } ) , { ' a ' : 1 } )
self . assertEqual ( merge_dicts ( { ' a ' : 1 } , { } ) , { ' a ' : 1 } )
self . assertEqual ( merge_dicts ( { ' a ' : None } , { ' a ' : 1 } ) , { ' a ' : 1 } )
self . assertEqual ( merge_dicts ( { ' a ' : ' ' } , { ' a ' : 1 } ) , { ' a ' : ' ' } )
self . assertEqual ( merge_dicts ( { ' a ' : ' ' } , { ' a ' : ' abc ' } ) , { ' a ' : ' abc ' } )
self . assertEqual ( merge_dicts ( { ' a ' : None } , { ' a ' : ' ' } , { ' a ' : ' abc ' } ) , { ' a ' : ' abc ' } )
2015-12-20 07:07:14 +06:00
def test_encode_compat_str ( self ) :
self . assertEqual ( encode_compat_str ( b ' \xd1 \x82 \xd0 \xb5 \xd1 \x81 \xd1 \x82 ' , ' utf-8 ' ) , ' тест ' )
self . assertEqual ( encode_compat_str ( ' тест ' , ' utf-8 ' ) , ' тест ' )
2014-03-24 01:40:09 +01:00
def test_parse_iso8601 ( self ) :
self . assertEqual ( parse_iso8601 ( ' 2014-03-23T23:04:26+0100 ' ) , 1395612266 )
self . assertEqual ( parse_iso8601 ( ' 2014-03-23T22:04:26+0000 ' ) , 1395612266 )
self . assertEqual ( parse_iso8601 ( ' 2014-03-23T22:04:26Z ' ) , 1395612266 )
2014-10-29 20:10:00 +01:00
self . assertEqual ( parse_iso8601 ( ' 2014-03-23T22:04:26.1234Z ' ) , 1395612266 )
2015-10-28 21:40:22 +06:00
self . assertEqual ( parse_iso8601 ( ' 2015-09-29T08:27:31.727 ' ) , 1443515251 )
self . assertEqual ( parse_iso8601 ( ' 2015-09-29T08-27-31.727 ' ) , None )
2014-03-24 01:40:09 +01:00
2014-03-24 23:21:20 +01:00
def test_strip_jsonp ( self ) :
stripped = strip_jsonp ( ' cb ([ { " id " : " 532cb " , \n \n \n " x " : \n 3} \n ] \n ); ' )
d = json . loads ( stripped )
self . assertEqual ( d , [ { " id " : " 532cb " , " x " : 3 } ] )
2014-11-13 16:28:05 +01:00
stripped = strip_jsonp ( ' parseMetadata( { " STATUS " : " OK " }) \n \n \n //epc ' )
d = json . loads ( stripped )
self . assertEqual ( d , { ' STATUS ' : ' OK ' } )
2016-02-07 19:47:09 +06:00
stripped = strip_jsonp ( ' ps.embedHandler( { " status " : " success " }); ' )
d = json . loads ( stripped )
self . assertEqual ( d , { ' status ' : ' success ' } )
2017-05-26 21:58:18 +08:00
stripped = strip_jsonp ( ' window.cb && window.cb( { " status " : " success " }); ' )
d = json . loads ( stripped )
self . assertEqual ( d , { ' status ' : ' success ' } )
stripped = strip_jsonp ( ' window.cb && cb( { " status " : " success " }); ' )
d = json . loads ( stripped )
self . assertEqual ( d , { ' status ' : ' success ' } )
2018-07-21 12:30:18 +07:00
stripped = strip_jsonp ( ' ( { " status " : " success " }); ' )
d = json . loads ( stripped )
self . assertEqual ( d , { ' status ' : ' success ' } )
2017-05-26 21:58:18 +08:00
2019-05-23 23:58:35 +07:00
def test_strip_or_none ( self ) :
self . assertEqual ( strip_or_none ( ' abc ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' abc ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' abc ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' \t abc \t ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' \n \t abc \n \t ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' abc ' ) , ' abc ' )
self . assertEqual ( strip_or_none ( ' ' ) , ' ' )
self . assertEqual ( strip_or_none ( None ) , None )
self . assertEqual ( strip_or_none ( 42 ) , None )
self . assertEqual ( strip_or_none ( [ ] ) , None )
2014-08-10 11:08:56 +02:00
def test_uppercase_escape ( self ) :
2014-08-27 19:11:45 +02:00
self . assertEqual ( uppercase_escape ( ' aä ' ) , ' aä ' )
self . assertEqual ( uppercase_escape ( ' \\ U0001d550 ' ) , ' 𝕐 ' )
2014-03-24 23:21:20 +01:00
2015-05-04 21:53:05 +08:00
def test_lowercase_escape ( self ) :
self . assertEqual ( lowercase_escape ( ' aä ' ) , ' aä ' )
self . assertEqual ( lowercase_escape ( ' \\ u0026 ' ) , ' & ' )
2014-09-15 15:10:24 +02:00
def test_limit_length ( self ) :
self . assertEqual ( limit_length ( None , 12 ) , None )
self . assertEqual ( limit_length ( ' foo ' , 12 ) , ' foo ' )
self . assertTrue (
limit_length ( ' foo bar baz asd ' , 12 ) . startswith ( ' foo bar ' ) )
self . assertTrue ( ' ... ' in limit_length ( ' foo bar baz asd ' , 12 ) )
2016-09-02 22:57:48 +07:00
def test_mimetype2ext ( self ) :
self . assertEqual ( mimetype2ext ( None ) , None )
self . assertEqual ( mimetype2ext ( ' video/x-flv ' ) , ' flv ' )
self . assertEqual ( mimetype2ext ( ' application/x-mpegURL ' ) , ' m3u8 ' )
self . assertEqual ( mimetype2ext ( ' text/vtt ' ) , ' vtt ' )
self . assertEqual ( mimetype2ext ( ' text/vtt;charset=utf-8 ' ) , ' vtt ' )
self . assertEqual ( mimetype2ext ( ' text/html; charset=utf-8 ' ) , ' html ' )
2016-09-14 23:13:55 +07:00
def test_month_by_name ( self ) :
self . assertEqual ( month_by_name ( None ) , None )
self . assertEqual ( month_by_name ( ' December ' , ' en ' ) , 12 )
2016-09-14 23:57:01 +07:00
self . assertEqual ( month_by_name ( ' décembre ' , ' fr ' ) , 12 )
2016-09-14 23:13:55 +07:00
self . assertEqual ( month_by_name ( ' December ' ) , 12 )
2016-09-14 23:57:01 +07:00
self . assertEqual ( month_by_name ( ' décembre ' ) , None )
2016-09-14 23:13:55 +07:00
self . assertEqual ( month_by_name ( ' Unknown ' , ' unknown ' ) , None )
2016-03-16 18:48:06 +01:00
def test_parse_codecs ( self ) :
self . assertEqual ( parse_codecs ( ' ' ) , { } )
self . assertEqual ( parse_codecs ( ' avc1.77.30, mp4a.40.2 ' ) , {
' vcodec ' : ' avc1.77.30 ' ,
' acodec ' : ' mp4a.40.2 ' ,
} )
self . assertEqual ( parse_codecs ( ' mp4a.40.2 ' ) , {
' vcodec ' : ' none ' ,
' acodec ' : ' mp4a.40.2 ' ,
} )
self . assertEqual ( parse_codecs ( ' mp4a.40.5,avc1.42001e ' ) , {
' vcodec ' : ' avc1.42001e ' ,
' acodec ' : ' mp4a.40.5 ' ,
} )
self . assertEqual ( parse_codecs ( ' avc3.640028 ' ) , {
' vcodec ' : ' avc3.640028 ' ,
' acodec ' : ' none ' ,
} )
self . assertEqual ( parse_codecs ( ' , h264,,newcodec,aac ' ) , {
' vcodec ' : ' h264 ' ,
' acodec ' : ' aac ' ,
} )
2018-09-10 02:37:22 +07:00
self . assertEqual ( parse_codecs ( ' av01.0.05M.08 ' ) , {
' vcodec ' : ' av01.0.05M.08 ' ,
' acodec ' : ' none ' ,
} )
2019-06-14 01:56:17 +07:00
self . assertEqual ( parse_codecs ( ' theora, vorbis ' ) , {
' vcodec ' : ' theora ' ,
' acodec ' : ' vorbis ' ,
} )
self . assertEqual ( parse_codecs ( ' unknownvcodec, unknownacodec ' ) , {
' vcodec ' : ' unknownvcodec ' ,
' acodec ' : ' unknownacodec ' ,
} )
self . assertEqual ( parse_codecs ( ' unknown ' ) , { } )
2016-03-16 18:48:06 +01:00
2014-09-13 20:59:16 +07:00
def test_escape_rfc3986 ( self ) :
reserved = " !* ' ();:@&=+$,/?#[] "
unreserved = ' ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~ '
self . assertEqual ( escape_rfc3986 ( reserved ) , reserved )
self . assertEqual ( escape_rfc3986 ( unreserved ) , unreserved )
self . assertEqual ( escape_rfc3986 ( ' тест ' ) , ' % D1 %82% D0 % B5 % D1 %81% D1 % 82 ' )
self . assertEqual ( escape_rfc3986 ( ' % D1 %82% D0 % B5 % D1 %81% D1 % 82 ' ) , ' % D1 %82% D0 % B5 % D1 %81% D1 % 82 ' )
self . assertEqual ( escape_rfc3986 ( ' foo bar ' ) , ' foo % 20bar ' )
self . assertEqual ( escape_rfc3986 ( ' foo % 20bar ' ) , ' foo % 20bar ' )
def test_escape_url ( self ) :
self . assertEqual (
escape_url ( ' http://wowza.imust.org/srv/vod/telemb/new/UPLOAD/UPLOAD/20224_IncendieHavré_FD.mp4 ' ) ,
' http://wowza.imust.org/srv/vod/telemb/new/UPLOAD/UPLOAD/20224_IncendieHavre % CC % 81_FD.mp4 '
)
self . assertEqual (
escape_url ( ' http://www.ardmediathek.de/tv/Sturm-der-Liebe/Folge-2036-Zu-Mann-und-Frau-erklärt/Das-Erste/Video?documentId=22673108&bcastId=5290 ' ) ,
' http://www.ardmediathek.de/tv/Sturm-der-Liebe/Folge-2036-Zu-Mann-und-Frau-erkl % C3 % A4rt/Das-Erste/Video?documentId=22673108&bcastId=5290 '
)
self . assertEqual (
escape_url ( ' http://тест.рф/фрагмент ' ) ,
2016-03-23 23:20:28 +08:00
' http://xn--e1aybc.xn--p1ai/ % D1 %84% D1 %80% D0 % B0 % D0 % B3 % D0 % BC % D0 % B5 % D0 % BD % D1 % 82 '
2014-09-13 20:59:16 +07:00
)
self . assertEqual (
escape_url ( ' http://тест.рф/абв?абв=абв#абв ' ) ,
2016-03-23 23:23:26 +08:00
' http://xn--e1aybc.xn--p1ai/ % D0 % B0 % D0 % B1 % D0 % B2? % D0 % B0 % D0 % B1 % D0 % B2= % D0 % B0 % D0 % B1 % D0 % B2# % D0 % B0 % D0 % B1 % D0 % B2 '
2014-09-13 20:59:16 +07:00
)
self . assertEqual ( escape_url ( ' http://vimeo.com/56015672#at=0 ' ) , ' http://vimeo.com/56015672#at=0 ' )
2014-09-30 11:12:59 +02:00
def test_js_to_json_realworld ( self ) :
2014-09-30 07:56:24 +02:00
inp = ''' {
2014-09-30 11:12:59 +02:00
' clip ' : { ' provider ' : ' pseudo ' }
2014-09-30 07:56:24 +02:00
} '''
self . assertEqual ( js_to_json ( inp ) , ''' {
2014-09-30 11:12:59 +02:00
" clip " : { " provider " : " pseudo " }
2014-09-30 07:56:24 +02:00
} ''' )
json . loads ( js_to_json ( inp ) )
2014-09-30 11:12:59 +02:00
inp = ''' {
' playlist ' : [ { ' controls ' : { ' all ' : null } } ]
} '''
self . assertEqual ( js_to_json ( inp ) , ''' {
" playlist " : [ { " controls " : { " all " : null } } ]
} ''' )
2015-10-20 23:09:51 +06:00
inp = ''' " The CW \\ ' s \\ ' Crazy Ex-Girlfriend \\ ' " '''
self . assertEqual ( js_to_json ( inp ) , ''' " The CW ' s ' Crazy Ex-Girlfriend ' " ''' )
2015-02-18 23:59:50 +01:00
inp = ' " SAND Number: SAND 2013-7800P \\ nPresenter: Tom Russo \\ nHabanero Software Training - Xyce Software \\ nXyce, Sandia \\ u0027s " '
json_code = js_to_json ( inp )
self . assertEqual ( json . loads ( json_code ) , json . loads ( inp ) )
2016-05-14 20:39:58 +06:00
inp = ''' {
0 : { src : ' skipped ' , type : ' application/dash+xml ' } ,
1 : { src : ' skipped ' , type : ' application/vnd.apple.mpegURL ' } ,
} '''
self . assertEqual ( js_to_json ( inp ) , ''' {
" 0 " : { " src " : " skipped " , " type " : " application/dash+xml " } ,
" 1 " : { " src " : " skipped " , " type " : " application/vnd.apple.mpegURL " }
} ''' )
2016-06-16 11:00:54 +08:00
inp = ''' { " foo " :101} '''
self . assertEqual ( js_to_json ( inp ) , ''' { " foo " :101} ''' )
2016-08-19 20:37:17 +08:00
inp = ''' { " duration " : " 00:01:07 " } '''
self . assertEqual ( js_to_json ( inp ) , ''' { " duration " : " 00:01:07 " } ''' )
2018-01-20 16:54:21 +01:00
inp = ''' { segments: [ { " offset " :-3.885780586188048e-16, " duration " :39.75000000000001}]} '''
self . assertEqual ( js_to_json ( inp ) , ''' { " segments " : [ { " offset " :-3.885780586188048e-16, " duration " :39.75000000000001}]} ''' )
2014-09-30 11:12:59 +02:00
def test_js_to_json_edgecases ( self ) :
on = js_to_json ( " { abc_def: ' 1 \\ ' \\ \\ 2 \\ \\ \\ ' 3 \" 4 ' } " )
self . assertEqual ( json . loads ( on ) , { " abc_def " : " 1 ' \\ 2 \\ ' 3 \" 4 " } )
on = js_to_json ( ' { " abc " : true} ' )
self . assertEqual ( json . loads ( on ) , { ' abc ' : True } )
2015-02-02 21:48:54 +01:00
# Ignore JavaScript code as well
on = js_to_json ( ''' {
" x " : 1 ,
y : " a " ,
z : some . code
} ''' )
d = json . loads ( on )
self . assertEqual ( d [ ' x ' ] , 1 )
self . assertEqual ( d [ ' y ' ] , ' a ' )
2015-04-04 17:48:55 +06:00
on = js_to_json ( ' [ " abc " , " def " ,] ' )
self . assertEqual ( json . loads ( on ) , [ ' abc ' , ' def ' ] )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' [/*comment \n */ " abc " /*comment \n */,/*comment \n */ " def " ,/*comment \n */] ' )
self . assertEqual ( json . loads ( on ) , [ ' abc ' , ' def ' ] )
on = js_to_json ( ' [//comment \n " abc " //comment \n ,//comment \n " def " ,//comment \n ] ' )
self . assertEqual ( json . loads ( on ) , [ ' abc ' , ' def ' ] )
2015-04-04 17:48:55 +06:00
on = js_to_json ( ' { " abc " : " def " ,} ' )
self . assertEqual ( json . loads ( on ) , { ' abc ' : ' def ' } )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' { /*comment \n */ " abc " /*comment \n */:/*comment \n */ " def " /*comment \n */,/*comment \n */} ' )
self . assertEqual ( json . loads ( on ) , { ' abc ' : ' def ' } )
2016-03-13 12:29:15 +01:00
on = js_to_json ( ' { 0: /* " \n */ " ,] " , } ' )
self . assertEqual ( json . loads ( on ) , { ' 0 ' : ' ,] ' } )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' { /*comment \n */0/*comment \n */: /* " \n */ " ,] " , } ' )
self . assertEqual ( json . loads ( on ) , { ' 0 ' : ' ,] ' } )
2017-01-31 07:54:53 +01:00
on = js_to_json ( ' { 0: // comment \n 1 } ' )
self . assertEqual ( json . loads ( on ) , { ' 0 ' : 1 } )
2016-03-13 12:29:15 +01:00
on = js_to_json ( r ' [ " <p>x< \ /p> " ] ' )
self . assertEqual ( json . loads ( on ) , [ ' <p>x</p> ' ] )
on = js_to_json ( r ' [ " \ xaa " ] ' )
self . assertEqual ( json . loads ( on ) , [ ' \u00aa ' ] )
on = js_to_json ( " [ ' a \\ \n b ' ] " )
self . assertEqual ( json . loads ( on ) , [ ' ab ' ] )
2017-02-03 02:55:06 +07:00
on = js_to_json ( " /*comment \n */[/*comment \n */ ' a \\ \n b ' /*comment \n */]/*comment \n */ " )
self . assertEqual ( json . loads ( on ) , [ ' ab ' ] )
2016-05-14 20:39:58 +06:00
on = js_to_json ( ' { 0xff:0xff} ' )
self . assertEqual ( json . loads ( on ) , { ' 255 ' : 255 } )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' { /*comment \n */0xff/*comment \n */:/*comment \n */0xff/*comment \n */} ' )
self . assertEqual ( json . loads ( on ) , { ' 255 ' : 255 } )
2016-05-14 20:39:58 +06:00
on = js_to_json ( ' {077:077} ' )
self . assertEqual ( json . loads ( on ) , { ' 63 ' : 63 } )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' { /*comment \n */077/*comment \n */:/*comment \n */077/*comment \n */} ' )
self . assertEqual ( json . loads ( on ) , { ' 63 ' : 63 } )
2016-05-14 20:39:58 +06:00
on = js_to_json ( ' {42:42} ' )
self . assertEqual ( json . loads ( on ) , { ' 42 ' : 42 } )
2017-02-03 02:55:06 +07:00
on = js_to_json ( ' { /*comment \n */42/*comment \n */:/*comment \n */42/*comment \n */} ' )
self . assertEqual ( json . loads ( on ) , { ' 42 ' : 42 } )
2018-01-20 16:54:21 +01:00
on = js_to_json ( ' { 42:4.2e1} ' )
self . assertEqual ( json . loads ( on ) , { ' 42 ' : 42.0 } )
2018-01-20 22:58:48 +07:00
def test_js_to_json_malformed ( self ) :
self . assertEqual ( js_to_json ( ' 42a1 ' ) , ' 42 " a1 " ' )
self . assertEqual ( js_to_json ( ' 42a-1 ' ) , ' 42 " a " -1 ' )
2016-01-02 19:49:59 +00:00
def test_extract_attributes ( self ) :
self . assertEqual ( extract_attributes ( ' <e x= " y " > ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( " <e x= ' y ' > " ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e x=y> ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e x= " a \' b \' c " > ' ) , { ' x ' : " a ' b ' c " } )
self . assertEqual ( extract_attributes ( ' <e x= \' a " b " c \' > ' ) , { ' x ' : ' a " b " c ' } )
self . assertEqual ( extract_attributes ( ' <e x= " y " > ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e x= " y " > ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e x= " & " > ' ) , { ' x ' : ' & ' } ) # XML
self . assertEqual ( extract_attributes ( ' <e x= " " " > ' ) , { ' x ' : ' " ' } )
2016-03-16 21:50:04 +06:00
self . assertEqual ( extract_attributes ( ' <e x= " £ " > ' ) , { ' x ' : ' £ ' } ) # HTML 3.2
self . assertEqual ( extract_attributes ( ' <e x= " λ " > ' ) , { ' x ' : ' λ ' } ) # HTML 4.0
2016-01-02 19:49:59 +00:00
self . assertEqual ( extract_attributes ( ' <e x= " &foo " > ' ) , { ' x ' : ' &foo ' } )
self . assertEqual ( extract_attributes ( ' <e x= " \' " > ' ) , { ' x ' : " ' " } )
self . assertEqual ( extract_attributes ( ' <e x= \' " \' > ' ) , { ' x ' : ' " ' } )
self . assertEqual ( extract_attributes ( ' <e x > ' ) , { ' x ' : None } )
self . assertEqual ( extract_attributes ( ' <e x=y a> ' ) , { ' x ' : ' y ' , ' a ' : None } )
self . assertEqual ( extract_attributes ( ' <e x= y> ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e x=1 y=2 x=3> ' ) , { ' y ' : ' 2 ' , ' x ' : ' 3 ' } )
self . assertEqual ( extract_attributes ( ' <e \n x= \n y \n > ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e \n x= \n " y " \n > ' ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( " <e \n x= \n ' y ' \n > " ) , { ' x ' : ' y ' } )
self . assertEqual ( extract_attributes ( ' <e \n x= " \n y \n " > ' ) , { ' x ' : ' \n y \n ' } )
2016-03-16 21:50:04 +06:00
self . assertEqual ( extract_attributes ( ' <e CAPS=x> ' ) , { ' caps ' : ' x ' } ) # Names lowercased
2016-01-02 19:49:59 +00:00
self . assertEqual ( extract_attributes ( ' <e x=1 X=2> ' ) , { ' x ' : ' 2 ' } )
self . assertEqual ( extract_attributes ( ' <e X=1 x=2> ' ) , { ' x ' : ' 2 ' } )
self . assertEqual ( extract_attributes ( ' <e _:funny-name1=1> ' ) , { ' _:funny-name1 ' : ' 1 ' } )
self . assertEqual ( extract_attributes ( ' <e x= " Fáilte 世界 \U0001f600 " > ' ) , { ' x ' : ' Fáilte 世界 \U0001f600 ' } )
self . assertEqual ( extract_attributes ( ' <e x= " décomposé " > ' ) , { ' x ' : ' décompose \u0301 ' } )
# "Narrow" Python builds don't support unicode code points outside BMP.
try :
compat_chr ( 0x10000 )
supports_outside_bmp = True
except ValueError :
supports_outside_bmp = False
if supports_outside_bmp :
self . assertEqual ( extract_attributes ( ' <e x= " Smile 😀! " > ' ) , { ' x ' : ' Smile \U0001f600 ! ' } )
2017-06-12 01:52:24 +07:00
# Malformed HTML should not break attributes extraction on older Python
self . assertEqual ( extract_attributes ( ' <mal " formed/> ' ) , { } )
2016-01-02 19:49:59 +00:00
2014-11-13 15:02:31 +01:00
def test_clean_html ( self ) :
self . assertEqual ( clean_html ( ' a: \n b ' ) , ' a: b ' )
self . assertEqual ( clean_html ( ' a: \n " b " ' ) , ' a: " b " ' )
2017-04-28 18:05:14 +02:00
self . assertEqual ( clean_html ( ' a<br> \xa0 b ' ) , ' a \n b ' )
2014-11-13 15:02:31 +01:00
2019-08-25 14:22:51 -05:00
def test_clean_html_markdown ( self ) :
self . assertEqual ( clean_html_markdown (
' <div id= " out " class= " markdown-body " ><h1>Happy Text</h1> \n '
' <p>When you do it your way you can go <em>anywhere</em> you choose. And just raise cain. I thought today we would make a happy little stream that \' s just running through the woods here. I was <strong>blessed</strong> with a very steady hand; and it comes in very handy when you \' re doing these little delicate things. You have to allow the paint to break to <strong><em>make it beautiful</em></strong>. Let \' s do it again then, what the heck.</p> \n '
' <h2>This is your creation - and it \' s just as unique and special as you are.</h2> \n '
' <p>Paint <b>anything</b> you want on the canvas. Create your own world. By now you should be quite happy about what \' s happening here. You can \' t have light without dark. You can \' t know <i>happiness</i> unless you \' ve known <em>sorrow</em>. Let \' s get crazy.</p> \n '
' <ul> \n '
' <li>You can spend all day playing with mountains.</li> \n '
' <li>We \' ll put a happy little sky in here.</li> \n '
' </ul> \n '
' <p>I like to beat the brush. There we go.<br> \n '
' We don \' t need any guidelines or formats. All we need to do is just let it flow right out of us. Trees live in your fan brush, but you have to scare them out.</p> \n '
' </div> ' ) ,
" # Happy Text \n "
" \n "
" When you do it your way you can go *anywhere* you choose. And just raise cain. I thought today we would make a happy little stream that ' s just running through the woods here. I was **blessed** with a very steady hand; and it comes in very handy when you ' re doing these little delicate things. You have to allow the paint to break to ***make it beautiful***. Let ' s do it again then, what the heck. \n "
" \n "
" ## This is your creation - and it ' s just as unique and special as you are. \n "
" \n "
" Paint **anything** you want on the canvas. Create your own world. By now you should be quite happy about what ' s happening here. You can ' t have light without dark. You can ' t know *happiness* unless you ' ve known *sorrow*. Let ' s get crazy. \n "
" \n "
" - You can spend all day playing with mountains. \n "
" - We ' ll put a happy little sky in here. \n "
" \n "
" I like to beat the brush. There we go. \n "
" We don ' t need any guidelines or formats. All we need to do is just let it flow right out of us. Trees live in your fan brush, but you have to scare them out. " )
2014-11-13 15:28:42 +01:00
def test_intlist_to_bytes ( self ) :
self . assertEqual (
intlist_to_bytes ( [ 0 , 1 , 127 , 128 , 255 ] ) ,
b ' \x00 \x01 \x7f \x80 \xff ' )
2014-11-23 10:49:19 +01:00
def test_args_to_str ( self ) :
self . assertEqual (
args_to_str ( [ ' foo ' , ' ba/r ' , ' -baz ' , ' 2 be ' , ' ' ] ) ,
2017-07-06 00:25:37 +07:00
' foo ba/r -baz \' 2 be \' \' \' ' if compat_os_name != ' nt ' else ' foo ba/r -baz " 2 be " " " '
2014-11-23 10:49:19 +01:00
)
2014-11-25 09:54:54 +01:00
def test_parse_filesize ( self ) :
self . assertEqual ( parse_filesize ( None ) , None )
self . assertEqual ( parse_filesize ( ' ' ) , None )
self . assertEqual ( parse_filesize ( ' 91 B ' ) , 91 )
self . assertEqual ( parse_filesize ( ' foobar ' ) , None )
self . assertEqual ( parse_filesize ( ' 2 MiB ' ) , 2097152 )
self . assertEqual ( parse_filesize ( ' 5 GB ' ) , 5000000000 )
self . assertEqual ( parse_filesize ( ' 1.2Tb ' ) , 1200000000000 )
2016-08-18 23:32:00 +07:00
self . assertEqual ( parse_filesize ( ' 1.2tb ' ) , 1200000000000 )
2014-12-04 17:02:05 +01:00
self . assertEqual ( parse_filesize ( ' 1,24 KB ' ) , 1240 )
2016-08-18 23:32:00 +07:00
self . assertEqual ( parse_filesize ( ' 1,24 kb ' ) , 1240 )
2016-08-20 00:12:32 +08:00
self . assertEqual ( parse_filesize ( ' 8.5 megabytes ' ) , 8500000 )
2014-11-25 09:54:54 +01:00
2016-03-13 16:27:20 +06:00
def test_parse_count ( self ) :
self . assertEqual ( parse_count ( None ) , None )
self . assertEqual ( parse_count ( ' ' ) , None )
self . assertEqual ( parse_count ( ' 0 ' ) , 0 )
self . assertEqual ( parse_count ( ' 1000 ' ) , 1000 )
self . assertEqual ( parse_count ( ' 1.000 ' ) , 1000 )
self . assertEqual ( parse_count ( ' 1.1k ' ) , 1100 )
self . assertEqual ( parse_count ( ' 1.1kk ' ) , 1100000 )
2016-03-19 11:42:35 +01:00
self . assertEqual ( parse_count ( ' 1.1kk ' ) , 1100000 )
self . assertEqual ( parse_count ( ' 1.1kk views ' ) , 1100000 )
2016-03-13 16:27:20 +06:00
2018-03-02 23:39:04 +07:00
def test_parse_resolution ( self ) :
self . assertEqual ( parse_resolution ( None ) , { } )
self . assertEqual ( parse_resolution ( ' ' ) , { } )
self . assertEqual ( parse_resolution ( ' 1920x1080 ' ) , { ' width ' : 1920 , ' height ' : 1080 } )
self . assertEqual ( parse_resolution ( ' 1920× 1080 ' ) , { ' width ' : 1920 , ' height ' : 1080 } )
self . assertEqual ( parse_resolution ( ' 1920 x 1080 ' ) , { ' width ' : 1920 , ' height ' : 1080 } )
self . assertEqual ( parse_resolution ( ' 720p ' ) , { ' height ' : 720 } )
self . assertEqual ( parse_resolution ( ' 4k ' ) , { ' height ' : 2160 } )
self . assertEqual ( parse_resolution ( ' 8K ' ) , { ' height ' : 4320 } )
2019-03-17 09:07:47 +07:00
def test_parse_bitrate ( self ) :
self . assertEqual ( parse_bitrate ( None ) , None )
self . assertEqual ( parse_bitrate ( ' ' ) , None )
self . assertEqual ( parse_bitrate ( ' 300kbps ' ) , 300 )
self . assertEqual ( parse_bitrate ( ' 1500kbps ' ) , 1500 )
self . assertEqual ( parse_bitrate ( ' 300 kbps ' ) , 300 )
2014-12-06 12:14:26 +01:00
def test_version_tuple ( self ) :
self . assertEqual ( version_tuple ( ' 1 ' ) , ( 1 , ) )
self . assertEqual ( version_tuple ( ' 10.23.344 ' ) , ( 10 , 23 , 344 ) )
2014-12-06 12:36:23 +01:00
self . assertEqual ( version_tuple ( ' 10.1-6 ' ) , ( 10 , 1 , 6 ) ) # avconv style
2014-12-06 12:14:26 +01:00
2014-12-14 21:59:59 +01:00
def test_detect_exe_version ( self ) :
self . assertEqual ( detect_exe_version ( ''' ffmpeg version 1.2.1
built on May 27 2013 08 : 37 : 26 with gcc 4.7 ( Debian 4.7 .3 - 4 )
configuration : - - prefix = / usr - - extra - ''' ), ' 1.2.1 ' )
self . assertEqual ( detect_exe_version ( ''' ffmpeg version N-63176-g1fb4685
built on May 15 2014 22 : 09 : 06 with gcc 4.8 .2 ( GCC ) ''' ), ' N-63176-g1fb4685 ' )
self . assertEqual ( detect_exe_version ( ''' X server found. dri2 connection failed!
Trying to open render node . . .
Success at / dev / dri / renderD128 .
ffmpeg version 2.4 .4 Copyright ( c ) 2000 - 2014 the FFmpeg . . . ''' ), ' 2.4.4 ' )
2015-01-07 07:20:20 +01:00
def test_age_restricted ( self ) :
self . assertFalse ( age_restricted ( None , 10 ) ) # unrestricted content
self . assertFalse ( age_restricted ( 1 , None ) ) # unrestricted policy
self . assertFalse ( age_restricted ( 8 , 10 ) )
self . assertTrue ( age_restricted ( 18 , 14 ) )
self . assertFalse ( age_restricted ( 18 , 18 ) )
2015-01-23 01:21:30 +01:00
def test_is_html ( self ) :
self . assertFalse ( is_html ( b ' \x49 \x44 \x43 <html ' ) )
self . assertTrue ( is_html ( b ' <!DOCTYPE foo> \xaa a ' ) )
self . assertTrue ( is_html ( # UTF-8 with BOM
b ' \xef \xbb \xbf <!DOCTYPE foo> \xaa a ' ) )
self . assertTrue ( is_html ( # UTF-16-LE
b ' \xff \xfe < \x00 h \x00 t \x00 m \x00 l \x00 > \x00 \xe4 \x00 '
) )
self . assertTrue ( is_html ( # UTF-16-BE
b ' \xfe \xff \x00 < \x00 h \x00 t \x00 m \x00 l \x00 > \x00 \xe4 '
) )
self . assertTrue ( is_html ( # UTF-32-BE
b ' \x00 \x00 \xFE \xFF \x00 \x00 \x00 < \x00 \x00 \x00 h \x00 \x00 \x00 t \x00 \x00 \x00 m \x00 \x00 \x00 l \x00 \x00 \x00 > \x00 \x00 \x00 \xe4 ' ) )
self . assertTrue ( is_html ( # UTF-32-LE
b ' \xFF \xFE \x00 \x00 < \x00 \x00 \x00 h \x00 \x00 \x00 t \x00 \x00 \x00 m \x00 \x00 \x00 l \x00 \x00 \x00 > \x00 \x00 \x00 \xe4 \x00 \x00 \x00 ' ) )
2015-01-25 02:38:47 +01:00
def test_render_table ( self ) :
self . assertEqual (
render_table (
[ ' a ' , ' bcd ' ] ,
[ [ 123 , 4 ] , [ 9999 , 51 ] ] ) ,
' a bcd \n '
' 123 4 \n '
' 9999 51 ' )
2015-02-10 03:32:21 +01:00
def test_match_str ( self ) :
self . assertRaises ( ValueError , match_str , ' xy>foobar ' , { } )
self . assertFalse ( match_str ( ' xy ' , { ' x ' : 1200 } ) )
self . assertTrue ( match_str ( ' !xy ' , { ' x ' : 1200 } ) )
self . assertTrue ( match_str ( ' x ' , { ' x ' : 1200 } ) )
self . assertFalse ( match_str ( ' !x ' , { ' x ' : 1200 } ) )
self . assertTrue ( match_str ( ' x ' , { ' x ' : 0 } ) )
self . assertFalse ( match_str ( ' x>0 ' , { ' x ' : 0 } ) )
self . assertFalse ( match_str ( ' x>0 ' , { } ) )
self . assertTrue ( match_str ( ' x>?0 ' , { } ) )
self . assertTrue ( match_str ( ' x>1K ' , { ' x ' : 1200 } ) )
self . assertFalse ( match_str ( ' x>2K ' , { ' x ' : 1200 } ) )
self . assertTrue ( match_str ( ' x>=1200 & x < 1300 ' , { ' x ' : 1200 } ) )
self . assertFalse ( match_str ( ' x>=1100 & x < 1200 ' , { ' x ' : 1200 } ) )
self . assertFalse ( match_str ( ' y=a212 ' , { ' y ' : ' foobar42 ' } ) )
self . assertTrue ( match_str ( ' y=foobar42 ' , { ' y ' : ' foobar42 ' } ) )
self . assertFalse ( match_str ( ' y!=foobar42 ' , { ' y ' : ' foobar42 ' } ) )
self . assertTrue ( match_str ( ' y!=foobar2 ' , { ' y ' : ' foobar42 ' } ) )
self . assertFalse ( match_str (
' like_count > 100 & dislike_count <? 50 & description ' ,
{ ' like_count ' : 90 , ' description ' : ' foo ' } ) )
self . assertTrue ( match_str (
' like_count > 100 & dislike_count <? 50 & description ' ,
{ ' like_count ' : 190 , ' description ' : ' foo ' } ) )
self . assertFalse ( match_str (
' like_count > 100 & dislike_count <? 50 & description ' ,
{ ' like_count ' : 190 , ' dislike_count ' : 60 , ' description ' : ' foo ' } ) )
self . assertFalse ( match_str (
' like_count > 100 & dislike_count <? 50 & description ' ,
{ ' like_count ' : 190 , ' dislike_count ' : 10 } ) )
2018-04-24 23:49:30 +07:00
self . assertTrue ( match_str ( ' is_live ' , { ' is_live ' : True } ) )
self . assertFalse ( match_str ( ' is_live ' , { ' is_live ' : False } ) )
self . assertFalse ( match_str ( ' is_live ' , { ' is_live ' : None } ) )
self . assertFalse ( match_str ( ' is_live ' , { } ) )
self . assertFalse ( match_str ( ' !is_live ' , { ' is_live ' : True } ) )
self . assertTrue ( match_str ( ' !is_live ' , { ' is_live ' : False } ) )
self . assertTrue ( match_str ( ' !is_live ' , { ' is_live ' : None } ) )
self . assertTrue ( match_str ( ' !is_live ' , { } ) )
self . assertTrue ( match_str ( ' title ' , { ' title ' : ' abc ' } ) )
self . assertTrue ( match_str ( ' title ' , { ' title ' : ' ' } ) )
self . assertFalse ( match_str ( ' !title ' , { ' title ' : ' abc ' } ) )
self . assertFalse ( match_str ( ' !title ' , { ' title ' : ' ' } ) )
2015-02-10 03:32:21 +01:00
2015-04-25 23:15:05 +08:00
def test_parse_dfxp_time_expr ( self ) :
2015-12-19 18:21:42 +08:00
self . assertEqual ( parse_dfxp_time_expr ( None ) , None )
self . assertEqual ( parse_dfxp_time_expr ( ' ' ) , None )
2015-04-25 23:15:05 +08:00
self . assertEqual ( parse_dfxp_time_expr ( ' 0.1 ' ) , 0.1 )
self . assertEqual ( parse_dfxp_time_expr ( ' 0.1s ' ) , 0.1 )
self . assertEqual ( parse_dfxp_time_expr ( ' 00:00:01 ' ) , 1.0 )
self . assertEqual ( parse_dfxp_time_expr ( ' 00:00:01.100 ' ) , 1.1 )
2015-12-19 19:29:51 +08:00
self . assertEqual ( parse_dfxp_time_expr ( ' 00:00:01:100 ' ) , 1.1 )
2015-04-25 23:15:05 +08:00
def test_dfxp2srt ( self ) :
dfxp_data = ''' <?xml version= " 1.0 " encoding= " UTF-8 " ?>
< tt xmlns = " http://www.w3.org/ns/ttml " xml : lang = " en " xmlns : tts = " http://www.w3.org/ns/ttml#parameter " >
< body >
< div xml : lang = " en " >
< p begin = " 0 " end = " 1 " > The following line contains Chinese characters and special symbols < / p >
< p begin = " 1 " end = " 2 " > 第二行 < br / > ♪ ♪ < / p >
2015-05-12 12:47:37 +08:00
< p begin = " 2 " dur = " 1 " > < span > Third < br / > Line < / span > < / p >
2015-12-19 18:21:42 +08:00
< p begin = " 3 " end = " -1 " > Lines with invalid timestamps are ignored < / p >
< p begin = " -1 " end = " -1 " > Ignore , two < / p >
< p begin = " 3 " dur = " -1 " > Ignored , three < / p >
2015-04-25 23:15:05 +08:00
< / div >
< / body >
2017-09-16 12:18:38 +08:00
< / tt > ''' .encode( ' utf-8 ' )
2015-04-25 23:15:05 +08:00
srt_data = ''' 1
00 : 00 : 00 , 000 - - > 00 : 00 : 01 , 000
The following line contains Chinese characters and special symbols
2
00 : 00 : 01 , 000 - - > 00 : 00 : 02 , 000
第二行
♪ ♪
3
00 : 00 : 02 , 000 - - > 00 : 00 : 03 , 000
Third
Line
'''
self . assertEqual ( dfxp2srt ( dfxp_data ) , srt_data )
2015-05-19 00:45:01 +08:00
dfxp_data_no_default_namespace = ''' <?xml version= " 1.0 " encoding= " UTF-8 " ?>
< tt xml : lang = " en " xmlns : tts = " http://www.w3.org/ns/ttml#parameter " >
< body >
< div xml : lang = " en " >
< p begin = " 0 " end = " 1 " > The first line < / p >
< / div >
< / body >
2017-09-16 12:18:38 +08:00
< / tt > ''' .encode( ' utf-8 ' )
2015-05-19 00:45:01 +08:00
srt_data = ''' 1
00 : 00 : 00 , 000 - - > 00 : 00 : 01 , 000
The first line
'''
self . assertEqual ( dfxp2srt ( dfxp_data_no_default_namespace ) , srt_data )
2017-02-23 18:46:20 +01:00
dfxp_data_with_style = ''' <?xml version= " 1.0 " encoding= " utf-8 " ?>
< tt xmlns = " http://www.w3.org/2006/10/ttaf1 " xmlns : ttp = " http://www.w3.org/2006/10/ttaf1#parameter " ttp : timeBase = " media " xmlns : tts = " http://www.w3.org/2006/10/ttaf1#style " xml : lang = " en " xmlns : ttm = " http://www.w3.org/2006/10/ttaf1#metadata " >
< head >
< styling >
< style id = " s2 " style = " s0 " tts : color = " cyan " tts : fontWeight = " bold " / >
< style id = " s1 " style = " s0 " tts : color = " yellow " tts : fontStyle = " italic " / >
< style id = " s3 " style = " s0 " tts : color = " lime " tts : textDecoration = " underline " / >
< style id = " s0 " tts : backgroundColor = " black " tts : fontStyle = " normal " tts : fontSize = " 16 " tts : fontFamily = " sansSerif " tts : color = " white " / >
< / styling >
< / head >
< body tts : textAlign = " center " style = " s0 " >
< div >
< p begin = " 00:00:02.08 " id = " p0 " end = " 00:00:05.84 " > default style < span tts : color = " red " > custom style < / span > < / p >
< p style = " s2 " begin = " 00:00:02.08 " id = " p0 " end = " 00:00:05.84 " > < span tts : color = " lime " > part 1 < br / > < / span > < span tts : color = " cyan " > part 2 < / span > < / p >
< p style = " s3 " begin = " 00:00:05.84 " id = " p1 " end = " 00:00:09.56 " > line 3 < br / > part 3 < / p >
< p style = " s1 " tts : textDecoration = " underline " begin = " 00:00:09.56 " id = " p2 " end = " 00:00:12.36 " > < span style = " s2 " tts : color = " lime " > inner < br / > < / span > style < / p >
< / div >
< / body >
2017-09-16 12:18:38 +08:00
< / tt > ''' .encode( ' utf-8 ' )
2017-02-23 18:46:20 +01:00
srt_data = ''' 1
00 : 00 : 02 , 080 - - > 00 : 00 : 05 , 839
< font color = " white " face = " sansSerif " size = " 16 " > default style < font color = " red " > custom style < / font > < / font >
2
00 : 00 : 02 , 080 - - > 00 : 00 : 05 , 839
< b > < font color = " cyan " face = " sansSerif " size = " 16 " > < font color = " lime " > part 1
< / font > part 2 < / font > < / b >
3
00 : 00 : 05 , 839 - - > 00 : 00 : 09 , 560
< u > < font color = " lime " > line 3
part 3 < / font > < / u >
4
00 : 00 : 09 , 560 - - > 00 : 00 : 12 , 359
< i > < u > < font color = " yellow " > < font color = " lime " > inner
< / font > style < / font > < / u > < / i >
'''
self . assertEqual ( dfxp2srt ( dfxp_data_with_style ) , srt_data )
2017-09-16 12:18:38 +08:00
dfxp_data_non_utf8 = ''' <?xml version= " 1.0 " encoding= " UTF-16 " ?>
< tt xmlns = " http://www.w3.org/ns/ttml " xml : lang = " en " xmlns : tts = " http://www.w3.org/ns/ttml#parameter " >
< body >
< div xml : lang = " en " >
< p begin = " 0 " end = " 1 " > Line 1 < / p >
< p begin = " 1 " end = " 2 " > 第二行 < / p >
< / div >
< / body >
< / tt > ''' .encode( ' utf-16 ' )
srt_data = ''' 1
00 : 00 : 00 , 000 - - > 00 : 00 : 01 , 000
Line 1
2
00 : 00 : 01 , 000 - - > 00 : 00 : 02 , 000
第二行
'''
self . assertEqual ( dfxp2srt ( dfxp_data_non_utf8 ) , srt_data )
2015-09-05 03:07:19 +06:00
def test_cli_option ( self ) :
self . assertEqual ( cli_option ( { ' proxy ' : ' 127.0.0.1:3128 ' } , ' --proxy ' , ' proxy ' ) , [ ' --proxy ' , ' 127.0.0.1:3128 ' ] )
self . assertEqual ( cli_option ( { ' proxy ' : None } , ' --proxy ' , ' proxy ' ) , [ ] )
self . assertEqual ( cli_option ( { } , ' --proxy ' , ' proxy ' ) , [ ] )
2016-08-13 09:53:46 +01:00
self . assertEqual ( cli_option ( { ' retries ' : 10 } , ' --retries ' , ' retries ' ) , [ ' --retries ' , ' 10 ' ] )
2015-09-05 03:07:19 +06:00
def test_cli_valueless_option ( self ) :
self . assertEqual ( cli_valueless_option (
{ ' downloader ' : ' external ' } , ' --external-downloader ' , ' downloader ' , ' external ' ) , [ ' --external-downloader ' ] )
self . assertEqual ( cli_valueless_option (
{ ' downloader ' : ' internal ' } , ' --external-downloader ' , ' downloader ' , ' external ' ) , [ ] )
self . assertEqual ( cli_valueless_option (
{ ' nocheckcertificate ' : True } , ' --no-check-certificate ' , ' nocheckcertificate ' ) , [ ' --no-check-certificate ' ] )
self . assertEqual ( cli_valueless_option (
{ ' nocheckcertificate ' : False } , ' --no-check-certificate ' , ' nocheckcertificate ' ) , [ ] )
self . assertEqual ( cli_valueless_option (
{ ' checkcertificate ' : True } , ' --no-check-certificate ' , ' checkcertificate ' , False ) , [ ] )
self . assertEqual ( cli_valueless_option (
{ ' checkcertificate ' : False } , ' --no-check-certificate ' , ' checkcertificate ' , False ) , [ ' --no-check-certificate ' ] )
def test_cli_bool_option ( self ) :
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : True } , ' --no-check-certificate ' , ' nocheckcertificate ' ) ,
[ ' --no-check-certificate ' , ' true ' ] )
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : True } , ' --no-check-certificate ' , ' nocheckcertificate ' , separator = ' = ' ) ,
[ ' --no-check-certificate=true ' ] )
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : True } , ' --check-certificate ' , ' nocheckcertificate ' , ' false ' , ' true ' ) ,
[ ' --check-certificate ' , ' false ' ] )
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : True } , ' --check-certificate ' , ' nocheckcertificate ' , ' false ' , ' true ' , ' = ' ) ,
[ ' --check-certificate=false ' ] )
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : False } , ' --check-certificate ' , ' nocheckcertificate ' , ' false ' , ' true ' ) ,
[ ' --check-certificate ' , ' true ' ] )
self . assertEqual (
cli_bool_option (
{ ' nocheckcertificate ' : False } , ' --check-certificate ' , ' nocheckcertificate ' , ' false ' , ' true ' , ' = ' ) ,
[ ' --check-certificate=true ' ] )
2017-08-09 22:28:19 +07:00
self . assertEqual (
cli_bool_option (
{ } , ' --check-certificate ' , ' nocheckcertificate ' , ' false ' , ' true ' , ' = ' ) ,
[ ] )
2015-09-05 03:07:19 +06:00
2016-02-17 06:01:44 +08:00
def test_ohdave_rsa_encrypt ( self ) :
N = 0xab86b6371b5318aaa1d3c9e612a9f1264f372323c8c0f19875b5fc3b3fd3afcc1e5bec527aa94bfa85bffc157e4245aebda05389a5357b75115ac94f074aefcd
e = 65537
self . assertEqual (
ohdave_rsa_encrypt ( b ' aa111222 ' , e , N ) ,
' 726664bd9a23fd0c70f9f1b84aab5e3905ce1e45a584e9cbcf9bcc7510338fc1986d6c599ff990d923aa43c51c0d9013cd572e13bc58f4ae48f2ed8c0b0ba881 ' )
2015-01-25 02:38:47 +01:00
2017-02-27 18:50:19 +08:00
def test_pkcs1pad ( self ) :
data = [ 1 , 2 , 3 ]
padded_data = pkcs1pad ( data , 32 )
self . assertEqual ( padded_data [ : 2 ] , [ 0 , 2 ] )
self . assertEqual ( padded_data [ 28 : ] , [ 0 , 1 , 2 , 3 ] )
self . assertRaises ( ValueError , pkcs1pad , data , 8 )
2016-02-27 03:19:50 +08:00
def test_encode_base_n ( self ) :
self . assertEqual ( encode_base_n ( 0 , 30 ) , ' 0 ' )
self . assertEqual ( encode_base_n ( 80 , 30 ) , ' 2k ' )
custom_table = ' 9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA '
self . assertEqual ( encode_base_n ( 0 , 30 , custom_table ) , ' 9 ' )
self . assertEqual ( encode_base_n ( 80 , 30 , custom_table ) , ' 7P ' )
self . assertRaises ( ValueError , encode_base_n , 0 , 70 )
self . assertRaises ( ValueError , encode_base_n , 0 , 60 , custom_table )
2016-06-26 15:16:49 +08:00
def test_urshift ( self ) :
self . assertEqual ( urshift ( 3 , 1 ) , 1 )
self . assertEqual ( urshift ( - 3 , 1 ) , 2147483646 )
2016-07-06 20:02:52 +08:00
def test_get_element_by_class ( self ) :
html = '''
< span class = " foo bar " > nice < / span >
'''
self . assertEqual ( get_element_by_class ( ' foo ' , html ) , ' nice ' )
self . assertEqual ( get_element_by_class ( ' no-such-class ' , html ) , None )
2017-02-11 10:16:54 +01:00
def test_get_element_by_attribute ( self ) :
html = '''
< span class = " foo bar " > nice < / span >
'''
self . assertEqual ( get_element_by_attribute ( ' class ' , ' foo bar ' , html ) , ' nice ' )
self . assertEqual ( get_element_by_attribute ( ' class ' , ' foo ' , html ) , None )
self . assertEqual ( get_element_by_attribute ( ' class ' , ' no-such-foo ' , html ) , None )
2017-07-05 23:23:35 +08:00
html = '''
< div itemprop = " author " itemscope > foo < / div >
'''
self . assertEqual ( get_element_by_attribute ( ' itemprop ' , ' author ' , html ) , ' foo ' )
2017-02-11 10:16:54 +01:00
def test_get_elements_by_class ( self ) :
html = '''
< span class = " foo bar " > nice < / span > < span class = " foo bar " > also nice < / span >
'''
self . assertEqual ( get_elements_by_class ( ' foo ' , html ) , [ ' nice ' , ' also nice ' ] )
self . assertEqual ( get_elements_by_class ( ' no-such-class ' , html ) , [ ] )
def test_get_elements_by_attribute ( self ) :
html = '''
< span class = " foo bar " > nice < / span > < span class = " foo bar " > also nice < / span >
'''
self . assertEqual ( get_elements_by_attribute ( ' class ' , ' foo bar ' , html ) , [ ' nice ' , ' also nice ' ] )
self . assertEqual ( get_elements_by_attribute ( ' class ' , ' foo ' , html ) , [ ] )
self . assertEqual ( get_elements_by_attribute ( ' class ' , ' no-such-foo ' , html ) , [ ] )
2016-11-17 19:42:56 +08:00
2012-11-27 23:20:29 +01:00
if __name__ == ' __main__ ' :
2012-11-28 02:04:46 +01:00
unittest . main ( )