Compare commits
18 Commits
2014.11.13
...
2014.11.16
Author | SHA1 | Date | |
---|---|---|---|
|
0cf166ad4f | ||
|
2707b50ffe | ||
|
939fe70de0 | ||
|
89c15fe0b3 | ||
|
ec5f601670 | ||
|
8caa0c9779 | ||
|
e2548b5b25 | ||
|
bbefcf04bf | ||
|
c7b0add86f | ||
|
a0155d93d9 | ||
|
00d9ef0b70 | ||
|
0cc8888038 | ||
|
c735450e07 | ||
|
71f8c7ce7a | ||
|
5fee0eeac0 | ||
|
eb4157fd17 | ||
|
69ede8ef81 | ||
|
609a61e3e6 |
@@ -284,6 +284,10 @@ class TestUtil(unittest.TestCase):
|
|||||||
d = json.loads(stripped)
|
d = json.loads(stripped)
|
||||||
self.assertEqual(d, [{"id": "532cb", "x": 3}])
|
self.assertEqual(d, [{"id": "532cb", "x": 3}])
|
||||||
|
|
||||||
|
stripped = strip_jsonp('parseMetadata({"STATUS":"OK"})\n\n\n//epc')
|
||||||
|
d = json.loads(stripped)
|
||||||
|
self.assertEqual(d, {'STATUS': 'OK'})
|
||||||
|
|
||||||
def test_uppercase_escape(self):
|
def test_uppercase_escape(self):
|
||||||
self.assertEqual(uppercase_escape('aä'), 'aä')
|
self.assertEqual(uppercase_escape('aä'), 'aä')
|
||||||
self.assertEqual(uppercase_escape('\\U0001d550'), '𝕐')
|
self.assertEqual(uppercase_escape('\\U0001d550'), '𝕐')
|
||||||
|
@@ -288,6 +288,14 @@ if sys.version_info < (3, 0) and sys.platform == 'win32':
|
|||||||
else:
|
else:
|
||||||
compat_getpass = getpass.getpass
|
compat_getpass = getpass.getpass
|
||||||
|
|
||||||
|
# Old 2.6 and 2.7 releases require kwargs to be bytes
|
||||||
|
try:
|
||||||
|
(lambda x: x)(**{'x': 0})
|
||||||
|
except TypeError:
|
||||||
|
def compat_kwargs(kwargs):
|
||||||
|
return dict((bytes(k), v) for k, v in kwargs.items())
|
||||||
|
else:
|
||||||
|
compat_kwargs = lambda kwargs: kwargs
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'compat_HTTPError',
|
'compat_HTTPError',
|
||||||
@@ -299,6 +307,7 @@ __all__ = [
|
|||||||
'compat_html_entities',
|
'compat_html_entities',
|
||||||
'compat_html_parser',
|
'compat_html_parser',
|
||||||
'compat_http_client',
|
'compat_http_client',
|
||||||
|
'compat_kwargs',
|
||||||
'compat_ord',
|
'compat_ord',
|
||||||
'compat_parse_qs',
|
'compat_parse_qs',
|
||||||
'compat_print',
|
'compat_print',
|
||||||
|
@@ -71,11 +71,12 @@ class BlipTVIE(SubtitlesInfoExtractor):
|
|||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
lookup_id = mobj.group('lookup_id')
|
lookup_id = mobj.group('lookup_id')
|
||||||
|
|
||||||
# See https://github.com/rg3/youtube-dl/issues/857
|
# See https://github.com/rg3/youtube-dl/issues/857 and
|
||||||
|
# https://github.com/rg3/youtube-dl/issues/4197
|
||||||
if lookup_id:
|
if lookup_id:
|
||||||
info_page = self._download_webpage(
|
info_page = self._download_webpage(
|
||||||
'http://blip.tv/play/%s.x?p=1' % lookup_id, lookup_id, 'Resolving lookup id')
|
'http://blip.tv/play/%s.x?p=1' % lookup_id, lookup_id, 'Resolving lookup id')
|
||||||
video_id = self._search_regex(r'data-episode-id="([0-9]+)', info_page, 'video_id')
|
video_id = self._search_regex(r'config\.id\s*=\s*"([0-9]+)', info_page, 'video_id')
|
||||||
else:
|
else:
|
||||||
video_id = mobj.group('id')
|
video_id = mobj.group('id')
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ class ComedyCentralIE(MTVServicesInfoExtractor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ComedyCentralShowsIE(InfoExtractor):
|
class ComedyCentralShowsIE(MTVServicesInfoExtractor):
|
||||||
IE_DESC = 'The Daily Show / The Colbert Report'
|
IE_DESC = 'The Daily Show / The Colbert Report'
|
||||||
# urls can be abbreviations like :thedailyshow or :colbert
|
# urls can be abbreviations like :thedailyshow or :colbert
|
||||||
# urls for episodes like:
|
# urls for episodes like:
|
||||||
@@ -109,14 +109,6 @@ class ComedyCentralShowsIE(InfoExtractor):
|
|||||||
'400': (384, 216),
|
'400': (384, 216),
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _transform_rtmp_url(rtmp_video_url):
|
|
||||||
m = re.match(r'^rtmpe?://.*?/(?P<finalid>gsp\.comedystor/.*)$', rtmp_video_url)
|
|
||||||
if not m:
|
|
||||||
raise ExtractorError('Cannot transform RTMP url')
|
|
||||||
base = 'http://mtvnmobile.vo.llnwd.net/kip0/_pxn=1+_pxI0=Ripod-h264+_pxL0=undefined+_pxM0=+_pxK=18639+_pxE=mp4/44620/mtvnorigin/'
|
|
||||||
return base + m.group('finalid')
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url, re.VERBOSE)
|
mobj = re.match(self._VALID_URL, url, re.VERBOSE)
|
||||||
if mobj is None:
|
if mobj is None:
|
||||||
@@ -212,9 +204,6 @@ class ComedyCentralShowsIE(InfoExtractor):
|
|||||||
'ext': self._video_extensions.get(format, 'mp4'),
|
'ext': self._video_extensions.get(format, 'mp4'),
|
||||||
'height': h,
|
'height': h,
|
||||||
'width': w,
|
'width': w,
|
||||||
|
|
||||||
'format_note': 'HTTP 400 at the moment (patches welcome!)',
|
|
||||||
'preference': -100,
|
|
||||||
})
|
})
|
||||||
formats.append({
|
formats.append({
|
||||||
'format_id': 'rtmp-%s' % format,
|
'format_id': 'rtmp-%s' % format,
|
||||||
|
@@ -264,8 +264,6 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|||||||
if not lang_code:
|
if not lang_code:
|
||||||
continue
|
continue
|
||||||
sub_root = xml.etree.ElementTree.fromstring(subtitle)
|
sub_root = xml.etree.ElementTree.fromstring(subtitle)
|
||||||
if not sub_root:
|
|
||||||
subtitles[lang_code] = ''
|
|
||||||
if sub_format == 'ass':
|
if sub_format == 'ass':
|
||||||
subtitles[lang_code] = self._convert_subtitles_to_ass(sub_root)
|
subtitles[lang_code] = self._convert_subtitles_to_ass(sub_root)
|
||||||
else:
|
else:
|
||||||
|
@@ -10,7 +10,7 @@ from ..utils import (
|
|||||||
|
|
||||||
class GoldenMoustacheIE(InfoExtractor):
|
class GoldenMoustacheIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?goldenmoustache\.com/(?P<display_id>[\w-]+)-(?P<id>\d+)'
|
_VALID_URL = r'https?://(?:www\.)?goldenmoustache\.com/(?P<display_id>[\w-]+)-(?P<id>\d+)'
|
||||||
_TEST = {
|
_TESTS = [{
|
||||||
'url': 'http://www.goldenmoustache.com/suricate-le-poker-3700/',
|
'url': 'http://www.goldenmoustache.com/suricate-le-poker-3700/',
|
||||||
'md5': '0f904432fa07da5054d6c8beb5efb51a',
|
'md5': '0f904432fa07da5054d6c8beb5efb51a',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
@@ -21,7 +21,18 @@ class GoldenMoustacheIE(InfoExtractor):
|
|||||||
'thumbnail': 're:^https?://.*\.jpg$',
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
'view_count': int,
|
'view_count': int,
|
||||||
}
|
}
|
||||||
}
|
}, {
|
||||||
|
'url': 'http://www.goldenmoustache.com/le-lab-tout-effacer-mc-fly-et-carlito-55249/',
|
||||||
|
'md5': '27f0c50fb4dd5f01dc9082fc67cd5700',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '55249',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Le LAB - Tout Effacer (Mc Fly et Carlito)',
|
||||||
|
'description': 'md5:9b7fbf11023fb2250bd4b185e3de3b2a',
|
||||||
|
'thumbnail': 're:^https?://.*\.(?:png|jpg)$',
|
||||||
|
'view_count': int,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
@@ -30,7 +41,7 @@ class GoldenMoustacheIE(InfoExtractor):
|
|||||||
video_url = self._html_search_regex(
|
video_url = self._html_search_regex(
|
||||||
r'data-src-type="mp4" data-src="([^"]+)"', webpage, 'video URL')
|
r'data-src-type="mp4" data-src="([^"]+)"', webpage, 'video URL')
|
||||||
title = self._html_search_regex(
|
title = self._html_search_regex(
|
||||||
r'<title>(.*?) - Golden Moustache</title>', webpage, 'title')
|
r'<title>(.*?)(?: - Golden Moustache)?</title>', webpage, 'title')
|
||||||
thumbnail = self._og_search_thumbnail(webpage)
|
thumbnail = self._og_search_thumbnail(webpage)
|
||||||
description = self._og_search_description(webpage)
|
description = self._og_search_description(webpage)
|
||||||
view_count = int_or_none(self._html_search_regex(
|
view_count = int_or_none(self._html_search_regex(
|
||||||
|
@@ -16,7 +16,7 @@ class MailRuIE(InfoExtractor):
|
|||||||
'url': 'http://my.mail.ru/video/top#video=/mail/sonypicturesrus/75/76',
|
'url': 'http://my.mail.ru/video/top#video=/mail/sonypicturesrus/75/76',
|
||||||
'md5': 'dea205f03120046894db4ebb6159879a',
|
'md5': 'dea205f03120046894db4ebb6159879a',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '46301138',
|
'id': '46301138_76',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Новый Человек-Паук. Высокое напряжение. Восстание Электро',
|
'title': 'Новый Человек-Паук. Высокое напряжение. Восстание Электро',
|
||||||
'timestamp': 1393232740,
|
'timestamp': 1393232740,
|
||||||
@@ -30,7 +30,7 @@ class MailRuIE(InfoExtractor):
|
|||||||
'url': 'http://my.mail.ru/corp/hitech/video/news_hi-tech_mail_ru/1263.html',
|
'url': 'http://my.mail.ru/corp/hitech/video/news_hi-tech_mail_ru/1263.html',
|
||||||
'md5': '00a91a58c3402204dcced523777b475f',
|
'md5': '00a91a58c3402204dcced523777b475f',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '46843144',
|
'id': '46843144_1263',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Samsung Galaxy S5 Hammer Smash Fail Battery Explosion',
|
'title': 'Samsung Galaxy S5 Hammer Smash Fail Battery Explosion',
|
||||||
'timestamp': 1397217632,
|
'timestamp': 1397217632,
|
||||||
@@ -54,33 +54,36 @@ class MailRuIE(InfoExtractor):
|
|||||||
|
|
||||||
author = video_data['author']
|
author = video_data['author']
|
||||||
uploader = author['name']
|
uploader = author['name']
|
||||||
uploader_id = author['id']
|
uploader_id = author.get('id') or author.get('email')
|
||||||
|
view_count = video_data.get('views_count')
|
||||||
|
|
||||||
movie = video_data['movie']
|
meta_data = video_data['meta']
|
||||||
content_id = str(movie['contentId'])
|
content_id = '%s_%s' % (
|
||||||
title = movie['title']
|
meta_data.get('accId', ''), meta_data['itemId'])
|
||||||
|
title = meta_data['title']
|
||||||
if title.endswith('.mp4'):
|
if title.endswith('.mp4'):
|
||||||
title = title[:-4]
|
title = title[:-4]
|
||||||
thumbnail = movie['poster']
|
thumbnail = meta_data['poster']
|
||||||
duration = movie['duration']
|
duration = meta_data['duration']
|
||||||
|
timestamp = meta_data['timestamp']
|
||||||
view_count = video_data['views_count']
|
|
||||||
|
|
||||||
formats = [
|
formats = [
|
||||||
{
|
{
|
||||||
'url': video['url'],
|
'url': video['url'],
|
||||||
'format_id': video['name'],
|
'format_id': video['key'],
|
||||||
|
'height': int(video['key'].rstrip('p'))
|
||||||
} for video in video_data['videos']
|
} for video in video_data['videos']
|
||||||
]
|
]
|
||||||
|
self._sort_formats(formats)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': content_id,
|
'id': content_id,
|
||||||
'title': title,
|
'title': title,
|
||||||
'thumbnail': thumbnail,
|
'thumbnail': thumbnail,
|
||||||
'timestamp': video_data['timestamp'],
|
'timestamp': timestamp,
|
||||||
'uploader': uploader,
|
'uploader': uploader,
|
||||||
'uploader_id': uploader_id,
|
'uploader_id': uploader_id,
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
'view_count': view_count,
|
'view_count': view_count,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
}
|
}
|
||||||
|
@@ -186,7 +186,8 @@ class MTVServicesEmbeddedIE(MTVServicesInfoExtractor):
|
|||||||
def _get_feed_url(self, uri):
|
def _get_feed_url(self, uri):
|
||||||
video_id = self._id_from_uri(uri)
|
video_id = self._id_from_uri(uri)
|
||||||
site_id = uri.replace(video_id, '')
|
site_id = uri.replace(video_id, '')
|
||||||
config_url = 'http://media.mtvnservices.com/pmt/e1/players/{0}/config.xml'.format(site_id)
|
config_url = ('http://media.mtvnservices.com/pmt/e1/players/{0}/'
|
||||||
|
'context4/context5/config.xml'.format(site_id))
|
||||||
config_doc = self._download_xml(config_url, video_id)
|
config_doc = self._download_xml(config_url, video_id)
|
||||||
feed_node = config_doc.find('.//feed')
|
feed_node = config_doc.find('.//feed')
|
||||||
feed_url = feed_node.text.strip().split('?')[0]
|
feed_url = feed_node.text.strip().split('?')[0]
|
||||||
|
@@ -7,6 +7,7 @@ from ..utils import (
|
|||||||
unified_strdate,
|
unified_strdate,
|
||||||
parse_duration,
|
parse_duration,
|
||||||
qualities,
|
qualities,
|
||||||
|
strip_jsonp,
|
||||||
url_basename,
|
url_basename,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ class NPOIE(InfoExtractor):
|
|||||||
'http://e.omroep.nl/metadata/aflevering/%s' % video_id,
|
'http://e.omroep.nl/metadata/aflevering/%s' % video_id,
|
||||||
video_id,
|
video_id,
|
||||||
# We have to remove the javascript callback
|
# We have to remove the javascript callback
|
||||||
transform_source=lambda j: re.sub(r'parseMetadata\((.*?)\);\n//.*$', r'\1', j)
|
transform_source=strip_jsonp,
|
||||||
)
|
)
|
||||||
token_page = self._download_webpage(
|
token_page = self._download_webpage(
|
||||||
'http://ida.omroep.nl/npoplayer/i.js',
|
'http://ida.omroep.nl/npoplayer/i.js',
|
||||||
|
@@ -5,6 +5,7 @@ import re
|
|||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..compat import compat_urlparse
|
from ..compat import compat_urlparse
|
||||||
|
from .spiegeltv import SpiegeltvIE
|
||||||
|
|
||||||
|
|
||||||
class SpiegelIE(InfoExtractor):
|
class SpiegelIE(InfoExtractor):
|
||||||
@@ -42,7 +43,11 @@ class SpiegelIE(InfoExtractor):
|
|||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage, handle = self._download_webpage_handle(url, video_id)
|
||||||
|
|
||||||
|
# 302 to spiegel.tv, like http://www.spiegel.de/video/der-film-zum-wochenende-die-wahrheit-ueber-maenner-video-99003272.html
|
||||||
|
if SpiegeltvIE.suitable(handle.geturl()):
|
||||||
|
return self.url_result(handle.geturl(), 'Spiegeltv')
|
||||||
|
|
||||||
title = re.sub(r'\s+', ' ', self._html_search_regex(
|
title = re.sub(r'\s+', ' ', self._html_search_regex(
|
||||||
r'(?s)<(?:h1|div) class="module-title"[^>]*>(.*?)</(?:h1|div)>',
|
r'(?s)<(?:h1|div) class="module-title"[^>]*>(.*?)</(?:h1|div)>',
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
from ..utils import float_or_none
|
||||||
|
|
||||||
|
|
||||||
class SpiegeltvIE(InfoExtractor):
|
class SpiegeltvIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?spiegel\.tv/filme/(?P<id>[\-a-z0-9]+)'
|
_VALID_URL = r'https?://(?:www\.)?spiegel\.tv/(?:#/)?filme/(?P<id>[\-a-z0-9]+)'
|
||||||
_TEST = {
|
_TESTS = [{
|
||||||
'url': 'http://www.spiegel.tv/filme/flug-mh370/',
|
'url': 'http://www.spiegel.tv/filme/flug-mh370/',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'flug-mh370',
|
'id': 'flug-mh370',
|
||||||
@@ -20,12 +20,15 @@ class SpiegeltvIE(InfoExtractor):
|
|||||||
# rtmp download
|
# rtmp download
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
}
|
}
|
||||||
}
|
}, {
|
||||||
|
'url': 'http://www.spiegel.tv/#/filme/alleskino-die-wahrheit-ueber-maenner/',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
if '/#/' in url:
|
||||||
video_id = mobj.group('id')
|
url = url.replace('/#/', '/')
|
||||||
|
video_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
title = self._html_search_regex(r'<h1.*?>(.*?)</h1>', webpage, 'title')
|
title = self._html_search_regex(r'<h1.*?>(.*?)</h1>', webpage, 'title')
|
||||||
|
|
||||||
@@ -61,12 +64,8 @@ class SpiegeltvIE(InfoExtractor):
|
|||||||
})
|
})
|
||||||
|
|
||||||
description = media_json['subtitle']
|
description = media_json['subtitle']
|
||||||
duration = media_json['duration_in_ms'] / 1000.
|
duration = float_or_none(media_json.get('duration_in_ms'), scale=1000)
|
||||||
|
format = '16x9' if is_wide else '4x3'
|
||||||
if is_wide:
|
|
||||||
format = '16x9'
|
|
||||||
else:
|
|
||||||
format = '4x3'
|
|
||||||
|
|
||||||
url = server + 'mp4:' + uuid + '_spiegeltv_0500_' + format + '.m4v'
|
url = server + 'mp4:' + uuid + '_spiegeltv_0500_' + format + '.m4v'
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ import sys
|
|||||||
from .compat import (
|
from .compat import (
|
||||||
compat_expanduser,
|
compat_expanduser,
|
||||||
compat_getenv,
|
compat_getenv,
|
||||||
|
compat_kwargs,
|
||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
get_term_width,
|
get_term_width,
|
||||||
@@ -112,7 +113,7 @@ def parseOpts(overrideArguments=None):
|
|||||||
'conflict_handler': 'resolve',
|
'conflict_handler': 'resolve',
|
||||||
}
|
}
|
||||||
|
|
||||||
parser = optparse.OptionParser(**kw)
|
parser = optparse.OptionParser(**compat_kwargs(kw))
|
||||||
|
|
||||||
general = optparse.OptionGroup(parser, 'General Options')
|
general = optparse.OptionGroup(parser, 'General Options')
|
||||||
general.add_option(
|
general.add_option(
|
||||||
|
@@ -73,10 +73,22 @@ def preferredencoding():
|
|||||||
def write_json_file(obj, fn):
|
def write_json_file(obj, fn):
|
||||||
""" Encode obj as JSON and write it to fn, atomically """
|
""" Encode obj as JSON and write it to fn, atomically """
|
||||||
|
|
||||||
|
if sys.version_info < (3, 0):
|
||||||
|
encoding = get_filesystem_encoding()
|
||||||
|
# os.path.basename returns a bytes object, but NamedTemporaryFile
|
||||||
|
# will fail if the filename contains non ascii characters unless we
|
||||||
|
# use a unicode object
|
||||||
|
path_basename = lambda f: os.path.basename(fn).decode(encoding)
|
||||||
|
# the same for os.path.dirname
|
||||||
|
path_dirname = lambda f: os.path.dirname(fn).decode(encoding)
|
||||||
|
else:
|
||||||
|
path_basename = os.path.basename
|
||||||
|
path_dirname = os.path.dirname
|
||||||
|
|
||||||
args = {
|
args = {
|
||||||
'suffix': '.tmp',
|
'suffix': '.tmp',
|
||||||
'prefix': os.path.basename(fn) + '.',
|
'prefix': path_basename(fn) + '.',
|
||||||
'dir': os.path.dirname(fn),
|
'dir': path_dirname(fn),
|
||||||
'delete': False,
|
'delete': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,7 +855,7 @@ def bytes_to_intlist(bs):
|
|||||||
def intlist_to_bytes(xs):
|
def intlist_to_bytes(xs):
|
||||||
if not xs:
|
if not xs:
|
||||||
return b''
|
return b''
|
||||||
return struct.pack('%dB' % len(xs), *xs)
|
return struct_pack('%dB' % len(xs), *xs)
|
||||||
|
|
||||||
|
|
||||||
# Cross-platform file locking
|
# Cross-platform file locking
|
||||||
@@ -1331,7 +1343,8 @@ def parse_age_limit(s):
|
|||||||
|
|
||||||
|
|
||||||
def strip_jsonp(code):
|
def strip_jsonp(code):
|
||||||
return re.sub(r'(?s)^[a-zA-Z0-9_]+\s*\(\s*(.*)\);?\s*?\s*$', r'\1', code)
|
return re.sub(
|
||||||
|
r'(?s)^[a-zA-Z0-9_]+\s*\(\s*(.*)\);?\s*?(?://[^\n]*)*$', r'\1', code)
|
||||||
|
|
||||||
|
|
||||||
def js_to_json(code):
|
def js_to_json(code):
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
__version__ = '2014.11.13.2'
|
__version__ = '2014.11.16'
|
||||||
|
Reference in New Issue
Block a user