Improve --bidi-workaround support
This commit is contained in:
		| @@ -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) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Hagemeister
					Philipp Hagemeister