Improve --bidi-workaround support

This commit is contained in:
Philipp Hagemeister 2013-12-09 18:29:07 +01:00
parent 395293a889
commit 1c088fa89d
3 changed files with 55 additions and 49 deletions

View file

@ -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,39 +161,24 @@ 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
params['progress_with_newline'] = True
for fid in ['_screen_file', '_err_file']:
class FribidiOut(object):
def __init__(self, outfile, errfile):
self.outfile = outfile
self.process = subprocess.Popen(
['fribidi'],
stdin=subprocess.PIPE,
stdout=outfile,
stderr=errfile)
def write(self, s):
res = self.process.stdin.write(s)
self.flush()
return res
def flush(self):
return self.process.stdin.flush()
def isatty(self):
return self.outfile.isatty()
try: try:
vout = FribidiOut(getattr(self, fid), self._err_file) import pty
setattr(self, fid, vout) master, slave = pty.openpty()
width = get_term_width()
if width is None:
width_args = []
else:
width_args = ['-w', str(width)]
self._fribidi = subprocess.Popen(
['fribidi', '-c', 'UTF-8'] + width_args,
stdin=subprocess.PIPE,
stdout=slave,
stderr=self._err_file)
self._fribidi_channel = os.fdopen(master, 'rb')
except OSError as ose: except OSError as ose:
if ose.errno == 2: 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.') 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: else:
raise raise
@ -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)

View 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)

View file

@ -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