mirror of https://github.com/yt-dlp/yt-dlp.git
Fix color in `-q -F`
and convert `ydl._out_files`/`ydl._allow_colors` to `Namespace` Closes #3761
This commit is contained in:
parent
5faf6528fb
commit
591bb9d355
|
@ -545,17 +545,18 @@ class YoutubeDL:
|
||||||
self.cache = Cache(self)
|
self.cache = Cache(self)
|
||||||
|
|
||||||
windows_enable_vt_mode()
|
windows_enable_vt_mode()
|
||||||
self._out_files = {
|
stdout = sys.stderr if self.params.get('logtostderr') else sys.stdout
|
||||||
'error': sys.stderr,
|
self._out_files = Namespace(
|
||||||
'print': sys.stderr if self.params.get('logtostderr') else sys.stdout,
|
out=stdout,
|
||||||
'console': None if compat_os_name == 'nt' else next(
|
error=sys.stderr,
|
||||||
|
screen=sys.stderr if self.params.get('quiet') else stdout,
|
||||||
|
console=None if compat_os_name == 'nt' else next(
|
||||||
filter(supports_terminal_sequences, (sys.stderr, sys.stdout)), None)
|
filter(supports_terminal_sequences, (sys.stderr, sys.stdout)), None)
|
||||||
}
|
)
|
||||||
self._out_files['screen'] = sys.stderr if self.params.get('quiet') else self._out_files['print']
|
self._allow_colors = Namespace(**{
|
||||||
self._allow_colors = {
|
type_: not self.params.get('no_color') and supports_terminal_sequences(stream)
|
||||||
type_: not self.params.get('no_color') and supports_terminal_sequences(self._out_files[type_])
|
for type_, stream in self._out_files.items_ if type_ != 'console'
|
||||||
for type_ in ('screen', 'error')
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if sys.version_info < (3, 6):
|
if sys.version_info < (3, 6):
|
||||||
self.report_warning(
|
self.report_warning(
|
||||||
|
@ -612,14 +613,8 @@ class YoutubeDL:
|
||||||
import pty
|
import pty
|
||||||
master, slave = pty.openpty()
|
master, slave = pty.openpty()
|
||||||
width = compat_get_terminal_size().columns
|
width = compat_get_terminal_size().columns
|
||||||
if width is None:
|
width_args = [] if width is None else ['-w', str(width)]
|
||||||
width_args = []
|
sp_kwargs = {'stdin': subprocess.PIPE, 'stdout': slave, 'stderr': self._out_files.error}
|
||||||
else:
|
|
||||||
width_args = ['-w', str(width)]
|
|
||||||
sp_kwargs = dict(
|
|
||||||
stdin=subprocess.PIPE,
|
|
||||||
stdout=slave,
|
|
||||||
stderr=self._out_files['error'])
|
|
||||||
try:
|
try:
|
||||||
self._output_process = Popen(['bidiv'] + width_args, **sp_kwargs)
|
self._output_process = Popen(['bidiv'] + width_args, **sp_kwargs)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -792,7 +787,7 @@ class YoutubeDL:
|
||||||
self.deprecation_warning('"YoutubeDL.to_stdout" no longer accepts the argument quiet. Use "YoutubeDL.to_screen" instead')
|
self.deprecation_warning('"YoutubeDL.to_stdout" no longer accepts the argument quiet. Use "YoutubeDL.to_screen" instead')
|
||||||
self._write_string(
|
self._write_string(
|
||||||
'%s%s' % (self._bidi_workaround(message), ('' if skip_eol else '\n')),
|
'%s%s' % (self._bidi_workaround(message), ('' if skip_eol else '\n')),
|
||||||
self._out_files['print'])
|
self._out_files.out)
|
||||||
|
|
||||||
def to_screen(self, message, skip_eol=False, quiet=None):
|
def to_screen(self, message, skip_eol=False, quiet=None):
|
||||||
"""Print message to screen if not in quiet mode"""
|
"""Print message to screen if not in quiet mode"""
|
||||||
|
@ -803,7 +798,7 @@ class YoutubeDL:
|
||||||
return
|
return
|
||||||
self._write_string(
|
self._write_string(
|
||||||
'%s%s' % (self._bidi_workaround(message), ('' if skip_eol else '\n')),
|
'%s%s' % (self._bidi_workaround(message), ('' if skip_eol else '\n')),
|
||||||
self._out_files['screen'])
|
self._out_files.screen)
|
||||||
|
|
||||||
def to_stderr(self, message, only_once=False):
|
def to_stderr(self, message, only_once=False):
|
||||||
"""Print message to stderr"""
|
"""Print message to stderr"""
|
||||||
|
@ -811,12 +806,12 @@ class YoutubeDL:
|
||||||
if self.params.get('logger'):
|
if self.params.get('logger'):
|
||||||
self.params['logger'].error(message)
|
self.params['logger'].error(message)
|
||||||
else:
|
else:
|
||||||
self._write_string('%s\n' % self._bidi_workaround(message), self._out_files['error'], only_once=only_once)
|
self._write_string(f'{self._bidi_workaround(message)}\n' , self._out_files.error, only_once=only_once)
|
||||||
|
|
||||||
def _send_console_code(self, code):
|
def _send_console_code(self, code):
|
||||||
if compat_os_name == 'nt' or not self._out_files['console']:
|
if compat_os_name == 'nt' or not self._out_files.console:
|
||||||
return
|
return
|
||||||
self._write_string(code, self._out_files['console'])
|
self._write_string(code, self._out_files.console)
|
||||||
|
|
||||||
def to_console_title(self, message):
|
def to_console_title(self, message):
|
||||||
if not self.params.get('consoletitle', False):
|
if not self.params.get('consoletitle', False):
|
||||||
|
@ -906,13 +901,14 @@ class YoutubeDL:
|
||||||
text = fallback
|
text = fallback
|
||||||
return format_text(text, f) if allow_colors else text if fallback is None else fallback
|
return format_text(text, f) if allow_colors else text if fallback is None else fallback
|
||||||
|
|
||||||
|
def _format_out(self, *args, **kwargs):
|
||||||
|
return self._format_text(self._out_files.out, self._allow_colors.out, *args, **kwargs)
|
||||||
|
|
||||||
def _format_screen(self, *args, **kwargs):
|
def _format_screen(self, *args, **kwargs):
|
||||||
return self._format_text(
|
return self._format_text(self._out_files.screen, self._allow_colors.screen, *args, **kwargs)
|
||||||
self._out_files['screen'], self._allow_colors['screen'], *args, **kwargs)
|
|
||||||
|
|
||||||
def _format_err(self, *args, **kwargs):
|
def _format_err(self, *args, **kwargs):
|
||||||
return self._format_text(
|
return self._format_text(self._out_files.error, self._allow_colors.error, *args, **kwargs)
|
||||||
self._out_files['error'], self._allow_colors['error'], *args, **kwargs)
|
|
||||||
|
|
||||||
def report_warning(self, message, only_once=False):
|
def report_warning(self, message, only_once=False):
|
||||||
'''
|
'''
|
||||||
|
@ -3438,7 +3434,7 @@ class YoutubeDL:
|
||||||
|
|
||||||
def _list_format_headers(self, *headers):
|
def _list_format_headers(self, *headers):
|
||||||
if self.params.get('listformats_table', True) is not False:
|
if self.params.get('listformats_table', True) is not False:
|
||||||
return [self._format_screen(header, self.Styles.HEADERS) for header in headers]
|
return [self._format_out(header, self.Styles.HEADERS) for header in headers]
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
def _format_note(self, fdict):
|
def _format_note(self, fdict):
|
||||||
|
@ -3516,10 +3512,10 @@ class YoutubeDL:
|
||||||
] for f in formats if f.get('preference') is None or f['preference'] >= -1000]
|
] for f in formats if f.get('preference') is None or f['preference'] >= -1000]
|
||||||
return render_table(['format code', 'extension', 'resolution', 'note'], table, extra_gap=1)
|
return render_table(['format code', 'extension', 'resolution', 'note'], table, extra_gap=1)
|
||||||
|
|
||||||
delim = self._format_screen('\u2502', self.Styles.DELIM, '|', test_encoding=True)
|
delim = self._format_out('\u2502', self.Styles.DELIM, '|', test_encoding=True)
|
||||||
table = [
|
table = [
|
||||||
[
|
[
|
||||||
self._format_screen(format_field(f, 'format_id'), self.Styles.ID),
|
self._format_out(format_field(f, 'format_id'), self.Styles.ID),
|
||||||
format_field(f, 'ext'),
|
format_field(f, 'ext'),
|
||||||
format_field(f, func=self.format_resolution, ignore=('audio only', 'images')),
|
format_field(f, func=self.format_resolution, ignore=('audio only', 'images')),
|
||||||
format_field(f, 'fps', '\t%d'),
|
format_field(f, 'fps', '\t%d'),
|
||||||
|
@ -3531,15 +3527,15 @@ class YoutubeDL:
|
||||||
delim,
|
delim,
|
||||||
format_field(f, 'vcodec', default='unknown').replace(
|
format_field(f, 'vcodec', default='unknown').replace(
|
||||||
'none', 'images' if f.get('acodec') == 'none'
|
'none', 'images' if f.get('acodec') == 'none'
|
||||||
else self._format_screen('audio only', self.Styles.SUPPRESS)),
|
else self._format_out('audio only', self.Styles.SUPPRESS)),
|
||||||
format_field(f, 'vbr', '\t%dk'),
|
format_field(f, 'vbr', '\t%dk'),
|
||||||
format_field(f, 'acodec', default='unknown').replace(
|
format_field(f, 'acodec', default='unknown').replace(
|
||||||
'none', '' if f.get('vcodec') == 'none'
|
'none', '' if f.get('vcodec') == 'none'
|
||||||
else self._format_screen('video only', self.Styles.SUPPRESS)),
|
else self._format_out('video only', self.Styles.SUPPRESS)),
|
||||||
format_field(f, 'abr', '\t%dk'),
|
format_field(f, 'abr', '\t%dk'),
|
||||||
format_field(f, 'asr', '\t%dHz'),
|
format_field(f, 'asr', '\t%dHz'),
|
||||||
join_nonempty(
|
join_nonempty(
|
||||||
self._format_screen('UNSUPPORTED', 'light red') if f.get('ext') in ('f4f', 'f4m') else None,
|
self._format_out('UNSUPPORTED', 'light red') if f.get('ext') in ('f4f', 'f4m') else None,
|
||||||
format_field(f, 'language', '[%s]'),
|
format_field(f, 'language', '[%s]'),
|
||||||
join_nonempty(format_field(f, 'format_note'),
|
join_nonempty(format_field(f, 'format_note'),
|
||||||
format_field(f, 'container', ignore=(None, f.get('ext'))),
|
format_field(f, 'container', ignore=(None, f.get('ext'))),
|
||||||
|
@ -3552,7 +3548,7 @@ class YoutubeDL:
|
||||||
|
|
||||||
return render_table(
|
return render_table(
|
||||||
header_line, table, hide_empty=True,
|
header_line, table, hide_empty=True,
|
||||||
delim=self._format_screen('\u2500', self.Styles.DELIM, '-', test_encoding=True))
|
delim=self._format_out('\u2500', self.Styles.DELIM, '-', test_encoding=True))
|
||||||
|
|
||||||
def render_thumbnails_table(self, info_dict):
|
def render_thumbnails_table(self, info_dict):
|
||||||
thumbnails = list(info_dict.get('thumbnails') or [])
|
thumbnails = list(info_dict.get('thumbnails') or [])
|
||||||
|
@ -3610,11 +3606,14 @@ class YoutubeDL:
|
||||||
ret += ' (No VT)' if WINDOWS_VT_MODE is False else ' (No ANSI)'
|
ret += ' (No VT)' if WINDOWS_VT_MODE is False else ' (No ANSI)'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
encoding_str = 'Encodings: locale %s, fs %s, out %s, err %s, pref %s' % (
|
encoding_str = 'Encodings: locale %s, fs %s, pref %s, %s' % (
|
||||||
locale.getpreferredencoding(),
|
locale.getpreferredencoding(),
|
||||||
sys.getfilesystemencoding(),
|
sys.getfilesystemencoding(),
|
||||||
get_encoding(self._out_files['screen']), get_encoding(self._out_files['error']),
|
self.get_encoding(),
|
||||||
self.get_encoding())
|
', '.join(
|
||||||
|
f'{key} {get_encoding(stream)}' for key, stream in self._out_files.items_
|
||||||
|
if stream is not None and key != 'console')
|
||||||
|
)
|
||||||
|
|
||||||
logger = self.params.get('logger')
|
logger = self.params.get('logger')
|
||||||
if logger:
|
if logger:
|
||||||
|
|
|
@ -63,7 +63,7 @@ class YDLLogger:
|
||||||
# Do not print to files/pipes, loggers, or when --no-progress is used
|
# Do not print to files/pipes, loggers, or when --no-progress is used
|
||||||
if not self._ydl or self._ydl.params.get('noprogress') or self._ydl.params.get('logger'):
|
if not self._ydl or self._ydl.params.get('noprogress') or self._ydl.params.get('logger'):
|
||||||
return
|
return
|
||||||
file = self._ydl._out_files['error']
|
file = self._ydl._out_files.error
|
||||||
try:
|
try:
|
||||||
if not file.isatty():
|
if not file.isatty():
|
||||||
return
|
return
|
||||||
|
|
|
@ -282,9 +282,9 @@ class FileDownloader:
|
||||||
elif self.ydl.params.get('logger'):
|
elif self.ydl.params.get('logger'):
|
||||||
self._multiline = MultilineLogger(self.ydl.params['logger'], lines)
|
self._multiline = MultilineLogger(self.ydl.params['logger'], lines)
|
||||||
elif self.params.get('progress_with_newline'):
|
elif self.params.get('progress_with_newline'):
|
||||||
self._multiline = BreaklineStatusPrinter(self.ydl._out_files['screen'], lines)
|
self._multiline = BreaklineStatusPrinter(self.ydl._out_files.screen, lines)
|
||||||
else:
|
else:
|
||||||
self._multiline = MultilinePrinter(self.ydl._out_files['screen'], lines, not self.params.get('quiet'))
|
self._multiline = MultilinePrinter(self.ydl._out_files.screen, lines, not self.params.get('quiet'))
|
||||||
self._multiline.allow_colors = self._multiline._HAVE_FULLCAP and not self.params.get('no_color')
|
self._multiline.allow_colors = self._multiline._HAVE_FULLCAP and not self.params.get('no_color')
|
||||||
|
|
||||||
def _finish_multiline_status(self):
|
def _finish_multiline_status(self):
|
||||||
|
@ -301,7 +301,7 @@ class FileDownloader:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _report_progress_status(self, s, default_template):
|
def _report_progress_status(self, s, default_template):
|
||||||
for name, style in self.ProgressStyles._asdict().items():
|
for name, style in self.ProgressStyles.items_:
|
||||||
name = f'_{name}_str'
|
name = f'_{name}_str'
|
||||||
if name not in s:
|
if name not in s:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -5322,8 +5322,20 @@ class classproperty:
|
||||||
return self.f(cls)
|
return self.f(cls)
|
||||||
|
|
||||||
|
|
||||||
def Namespace(**kwargs):
|
class Namespace:
|
||||||
return collections.namedtuple('Namespace', kwargs)(**kwargs)
|
"""Immutable namespace"""
|
||||||
|
@property
|
||||||
|
def items_(self):
|
||||||
|
return self._dict.items()
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self._dict = kwargs
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return self._dict[attr]
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{type(self).__name__}({", ".join(f"{k}={v}" for k, v in self.items_)})'
|
||||||
|
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
|
|
Loading…
Reference in New Issue