Improve --bidi-workaround support
This commit is contained in:
parent
395293a889
commit
1c088fa89d
|
@ -33,6 +33,7 @@ from .utils import (
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
format_bytes,
|
format_bytes,
|
||||||
|
get_term_width,
|
||||||
locked_file,
|
locked_file,
|
||||||
make_HTTPS_handler,
|
make_HTTPS_handler,
|
||||||
MaxDownloadsReached,
|
MaxDownloadsReached,
|
||||||
|
@ -160,41 +161,26 @@ class YoutubeDL(object):
|
||||||
self._err_file = sys.stderr
|
self._err_file = sys.stderr
|
||||||
self.params = {} if params is None else params
|
self.params = {} if params is None else params
|
||||||
|
|
||||||
# Pipe messsages through fribidi
|
|
||||||
if params.get('bidi_workaround', False):
|
if params.get('bidi_workaround', False):
|
||||||
# fribidi does not support ungetting, so force newlines
|
try:
|
||||||
params['progress_with_newline'] = True
|
import pty
|
||||||
|
master, slave = pty.openpty()
|
||||||
for fid in ['_screen_file', '_err_file']:
|
width = get_term_width()
|
||||||
class FribidiOut(object):
|
if width is None:
|
||||||
def __init__(self, outfile, errfile):
|
width_args = []
|
||||||
self.outfile = outfile
|
else:
|
||||||
self.process = subprocess.Popen(
|
width_args = ['-w', str(width)]
|
||||||
['fribidi'],
|
self._fribidi = subprocess.Popen(
|
||||||
stdin=subprocess.PIPE,
|
['fribidi', '-c', 'UTF-8'] + width_args,
|
||||||
stdout=outfile,
|
stdin=subprocess.PIPE,
|
||||||
stderr=errfile)
|
stdout=slave,
|
||||||
|
stderr=self._err_file)
|
||||||
def write(self, s):
|
self._fribidi_channel = os.fdopen(master, 'rb')
|
||||||
res = self.process.stdin.write(s)
|
except OSError as ose:
|
||||||
self.flush()
|
if ose.errno == 2:
|
||||||
return res
|
self.report_warning(u'Could not find fribidi executable, ignoring --bidi-workaround . Make sure that fribidi is an executable file in one of the directories in your $PATH.')
|
||||||
|
else:
|
||||||
def flush(self):
|
raise
|
||||||
return self.process.stdin.flush()
|
|
||||||
|
|
||||||
def isatty(self):
|
|
||||||
return self.outfile.isatty()
|
|
||||||
|
|
||||||
try:
|
|
||||||
vout = FribidiOut(getattr(self, fid), self._err_file)
|
|
||||||
setattr(self, fid, vout)
|
|
||||||
except OSError as ose:
|
|
||||||
if ose.errno == 2:
|
|
||||||
self.report_warning(u'Could not find fribidi executable, ignoring --bidi-workaround . Make sure that fribidi is an executable file in one of the directories in your $PATH.')
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
if (sys.version_info >= (3,) and sys.platform != 'win32' and
|
if (sys.version_info >= (3,) and sys.platform != 'win32' and
|
||||||
sys.getfilesystemencoding() in ['ascii', 'ANSI_X3.4-1968']
|
sys.getfilesystemencoding() in ['ascii', 'ANSI_X3.4-1968']
|
||||||
|
@ -243,6 +229,18 @@ class YoutubeDL(object):
|
||||||
self._pps.append(pp)
|
self._pps.append(pp)
|
||||||
pp.set_downloader(self)
|
pp.set_downloader(self)
|
||||||
|
|
||||||
|
def _bidi_workaround(self, message):
|
||||||
|
if not hasattr(self, '_fribidi_channel'):
|
||||||
|
return message
|
||||||
|
|
||||||
|
assert type(message) == type(u'')
|
||||||
|
line_count = message.count(u'\n') + 1
|
||||||
|
self._fribidi.stdin.write((message + u'\n').encode('utf-8'))
|
||||||
|
self._fribidi.stdin.flush()
|
||||||
|
res = u''.join(self._fribidi_channel.readline().decode('utf-8')
|
||||||
|
for _ in range(line_count))
|
||||||
|
return res[:-len(u'\n')]
|
||||||
|
|
||||||
def to_screen(self, message, skip_eol=False):
|
def to_screen(self, message, skip_eol=False):
|
||||||
"""Print message to stdout if not in quiet mode."""
|
"""Print message to stdout if not in quiet mode."""
|
||||||
return self.to_stdout(message, skip_eol, check_quiet=True)
|
return self.to_stdout(message, skip_eol, check_quiet=True)
|
||||||
|
@ -252,8 +250,10 @@ class YoutubeDL(object):
|
||||||
if self.params.get('logger'):
|
if self.params.get('logger'):
|
||||||
self.params['logger'].debug(message)
|
self.params['logger'].debug(message)
|
||||||
elif not check_quiet or not self.params.get('quiet', False):
|
elif not check_quiet or not self.params.get('quiet', False):
|
||||||
|
message = self._bidi_workaround(message)
|
||||||
terminator = [u'\n', u''][skip_eol]
|
terminator = [u'\n', u''][skip_eol]
|
||||||
output = message + terminator
|
output = message + terminator
|
||||||
|
|
||||||
write_string(output, self._screen_file)
|
write_string(output, self._screen_file)
|
||||||
|
|
||||||
def to_stderr(self, message):
|
def to_stderr(self, message):
|
||||||
|
@ -262,6 +262,7 @@ class YoutubeDL(object):
|
||||||
if self.params.get('logger'):
|
if self.params.get('logger'):
|
||||||
self.params['logger'].error(message)
|
self.params['logger'].error(message)
|
||||||
else:
|
else:
|
||||||
|
message = self._bidi_workaround(message)
|
||||||
output = message + u'\n'
|
output = message + u'\n'
|
||||||
write_string(output, self._err_file)
|
write_string(output, self._err_file)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@ import os
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,6 +56,7 @@ from .utils import (
|
||||||
DateRange,
|
DateRange,
|
||||||
decodeOption,
|
decodeOption,
|
||||||
determine_ext,
|
determine_ext,
|
||||||
|
get_term_width,
|
||||||
DownloadError,
|
DownloadError,
|
||||||
get_cachedir,
|
get_cachedir,
|
||||||
MaxDownloadsReached,
|
MaxDownloadsReached,
|
||||||
|
@ -113,19 +113,6 @@ def parseOpts(overrideArguments=None):
|
||||||
def _comma_separated_values_options_callback(option, opt_str, value, parser):
|
def _comma_separated_values_options_callback(option, opt_str, value, parser):
|
||||||
setattr(parser.values, option.dest, value.split(','))
|
setattr(parser.values, option.dest, value.split(','))
|
||||||
|
|
||||||
def _find_term_columns():
|
|
||||||
columns = os.environ.get('COLUMNS', None)
|
|
||||||
if columns:
|
|
||||||
return int(columns)
|
|
||||||
|
|
||||||
try:
|
|
||||||
sp = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
out,err = sp.communicate()
|
|
||||||
return int(out.split()[1])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _hide_login_info(opts):
|
def _hide_login_info(opts):
|
||||||
opts = list(opts)
|
opts = list(opts)
|
||||||
for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
|
for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
|
||||||
|
@ -140,7 +127,7 @@ def parseOpts(overrideArguments=None):
|
||||||
max_help_position = 80
|
max_help_position = 80
|
||||||
|
|
||||||
# No need to wrap help messages if we're on a wide console
|
# No need to wrap help messages if we're on a wide console
|
||||||
columns = _find_term_columns()
|
columns = get_term_width()
|
||||||
if columns: max_width = columns
|
if columns: max_width = columns
|
||||||
|
|
||||||
fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
|
fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import platform
|
||||||
import re
|
import re
|
||||||
import ssl
|
import ssl
|
||||||
import socket
|
import socket
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import zlib
|
import zlib
|
||||||
|
@ -1024,6 +1025,23 @@ def format_bytes(bytes):
|
||||||
converted = float(bytes) / float(1024 ** exponent)
|
converted = float(bytes) / float(1024 ** exponent)
|
||||||
return u'%.2f%s' % (converted, suffix)
|
return u'%.2f%s' % (converted, suffix)
|
||||||
|
|
||||||
|
|
||||||
def str_to_int(int_str):
|
def str_to_int(int_str):
|
||||||
int_str = re.sub(r'[,\.]', u'', int_str)
|
int_str = re.sub(r'[,\.]', u'', int_str)
|
||||||
return int(int_str)
|
return int(int_str)
|
||||||
|
|
||||||
|
|
||||||
|
def get_term_width():
|
||||||
|
columns = os.environ.get('COLUMNS', None)
|
||||||
|
if columns:
|
||||||
|
return int(columns)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sp = subprocess.Popen(
|
||||||
|
['stty', 'size'],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
out, err = sp.communicate()
|
||||||
|
return int(out.split()[1])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
Loading…
Reference in New Issue