1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-19 00:17:51 +02:00

auto wrap warning and error messages

This commit is contained in:
Kelly Brazil
2021-09-23 20:53:31 -07:00
parent 224d3d65ad
commit b7433ed085
6 changed files with 80 additions and 41 deletions

View File

@ -4,14 +4,16 @@ jc - JSON CLI output utility utils
## warning_message ## warning_message
```python ```python
warning_message(message) warning_message(message_lines)
``` ```
Prints a warning message for non-fatal issues Prints warning message for non-fatal issues. The first line is appended with
'jc: Warning - ' and subsequent lines are indented. Wraps text as needed based
on the terminal width.
Parameters: Parameters:
message: (string) text of message message: (list) list of string lines
Returns: Returns:
@ -20,14 +22,16 @@ Returns:
## error_message ## error_message
```python ```python
error_message(message) error_message(message_lines)
``` ```
Prints an error message for fatal issues Prints an error message for fatal issues. The first line is appended with
'jc: Error - ' and subsequent lines are indented. Wraps text as needed based
on the terminal width.
Parameters: Parameters:
message: (string) text of message message: (list) list of string lines
Returns: Returns:

View File

@ -219,7 +219,7 @@ def set_env_colors(env_colors=None):
# if there is an issue with the env variable, just set all colors to default and move on # if there is an issue with the env variable, just set all colors to default and move on
if input_error: if input_error:
jc.utils.warning_message('Could not parse JC_COLORS environment variable') jc.utils.warning_message(['Could not parse JC_COLORS environment variable'])
color_list = ['default', 'default', 'default', 'default'] color_list = ['default', 'default', 'default', 'default']
# Try the color set in the JC_COLORS env variable first. If it is set to default, then fall back to default colors # Try the color set in the JC_COLORS env variable first. If it is set to default, then fall back to default colors
@ -569,25 +569,25 @@ def main():
if debug: if debug:
raise raise
else: else:
jc.utils.error_message(f'"{run_command_str}" command could not be found. For details use the -d or -dd option.') jc.utils.error_message([f'"{run_command_str}" command could not be found. For details use the -d or -dd option.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
except OSError: except OSError:
if debug: if debug:
raise raise
else: else:
jc.utils.error_message(f'"{run_command_str}" command could not be run due to too many open files. For details use the -d or -dd option.') jc.utils.error_message([f'"{run_command_str}" command could not be run due to too many open files. For details use the -d or -dd option.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
except Exception: except Exception:
if debug: if debug:
raise raise
else: else:
jc.utils.error_message(f'"{run_command_str}" command could not be run. For details use the -d or -dd option.') jc.utils.error_message([f'"{run_command_str}" command could not be run. For details use the -d or -dd option.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
elif run_command is not None: elif run_command is not None:
jc.utils.error_message(f'"{run_command_str}" cannot be used with Magic syntax. Use "jc -h" for help.') jc.utils.error_message([f'"{run_command_str}" cannot be used with Magic syntax. Use "jc -h" for help.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
# find the correct parser # find the correct parser
@ -606,16 +606,16 @@ def main():
break break
if not found: if not found:
jc.utils.error_message('Missing or incorrect arguments. Use "jc -h" for help.') jc.utils.error_message(['Missing or incorrect arguments. Use "jc -h" for help.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
# check for input errors (pipe vs magic) # check for input errors (pipe vs magic)
if not sys.stdin.isatty() and magic_stdout: if not sys.stdin.isatty() and magic_stdout:
jc.utils.error_message('Piped data and Magic syntax used simultaneously. Use "jc -h" for help.') jc.utils.error_message(['Piped data and Magic syntax used simultaneously. Use "jc -h" for help.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
elif sys.stdin.isatty() and magic_stdout is None: elif sys.stdin.isatty() and magic_stdout is None:
jc.utils.error_message('Missing piped data. Use "jc -h" for help.') jc.utils.error_message(['Missing piped data. Use "jc -h" for help.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
# parse and print to stdout # parse and print to stdout
@ -652,19 +652,17 @@ def main():
if debug: if debug:
raise raise
else: else:
jc.utils.error_message( jc.utils.error_message([f'Parser issue with {parser_name}:',
f'Parser issue with {parser_name}:\n' f'{e.__class__.__name__}: {e}',
f' {e.__class__.__name__}: {e}\n' 'For details use the -d or -dd option. Use "jc -h" for help.'])
' For details use the -d or -dd option. Use "jc -h" for help.')
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
except json.JSONDecodeError: except json.JSONDecodeError:
if debug: if debug:
raise raise
else: else:
jc.utils.error_message( jc.utils.error_message(['There was an issue generating the JSON output.',
'There was an issue generating the JSON output.\n' 'For details use the -d or -dd option.'])
' For details use the -d or -dd option.')
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
except Exception: except Exception:
@ -673,12 +671,13 @@ def main():
else: else:
streaming_msg = '' streaming_msg = ''
if getattr(parser.info, 'streaming', None): if getattr(parser.info, 'streaming', None):
streaming_msg = ' Use the -qq option to ignore streaming parser errors.\n' streaming_msg = 'Use the -qq option to ignore streaming parser errors.'
jc.utils.error_message( jc.utils.error_message([
f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n' f'{parser_name} parser could not parse the input data. Did you use the correct parser?',
f'{streaming_msg}' f'{streaming_msg}',
' For details use the -d or -dd option. Use "jc -h" for help.') 'For details use the -d or -dd option. Use "jc -h" for help.'
])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))

View File

@ -130,7 +130,7 @@ def parse(data, raw=False, quiet=False):
) )
except IndexError: except IndexError:
if not warned: if not warned:
jc.utils.warning_message('Filenames with newline characters detected. Some filenames may be truncated.') jc.utils.warning_message(['Filenames with newline characters detected. Some filenames may be truncated.'])
warned = True warned = True
if raw: if raw:

View File

@ -255,7 +255,7 @@ def parse(data, raw=False, quiet=False):
continue continue
if not quiet and next_is_parent and not entry.endswith(':') and not warned: if not quiet and next_is_parent and not entry.endswith(':') and not warned:
jc.utils.warning_message('Newline characters detected. Filenames probably corrupted. Use ls -l or -b instead.') jc.utils.warning_message(['Newline characters detected. Filenames probably corrupted. Use ls -l or -b instead.'])
warned = True warned = True
output_line['filename'] = entry output_line['filename'] = entry

View File

@ -389,7 +389,7 @@ def parse(data, raw=False, quiet=False):
# print warning to STDERR # print warning to STDERR
if not quiet: if not quiet:
jc.utils.warning_message('No header row found. For destination info redirect STDERR to STDOUT') jc.utils.warning_message(['No header row found. For destination info redirect STDERR to STDOUT'])
data = '\n'.join(new_data) data = '\n'.join(new_data)

View File

@ -2,41 +2,77 @@
import sys import sys
import re import re
import locale import locale
import shutil
from datetime import datetime, timezone from datetime import datetime, timezone
from textwrap import TextWrapper
def warning_message(message): def warning_message(message_lines):
""" """
Prints a warning message for non-fatal issues Prints warning message for non-fatal issues. The first line is appended with
'jc: Warning - ' and subsequent lines are indented. Wraps text as needed based
on the terminal width.
Parameters: Parameters:
message: (string) text of message message: (list) list of string lines
Returns: Returns:
None - just prints output to STDERR None - just prints output to STDERR
""" """
# this is for backwards compatibility with existing custom parsers
if isinstance(message_lines, str):
message_lines = [message_lines]
error_string = f'jc: Warning - {message}' columns = shutil.get_terminal_size().columns
print(error_string, file=sys.stderr)
first_wrapper = TextWrapper(width=columns, subsequent_indent=' ' * 15)
next_wrapper = TextWrapper(width=columns, initial_indent=' ' * 15,
subsequent_indent=' ' * 15)
first_line = message_lines.pop(0)
first_str = f'jc: Warning - {first_line}'
first_str = first_wrapper.fill(first_str)
print(first_str, file=sys.stderr)
for line in message_lines:
if line == '':
continue
message = next_wrapper.fill(line)
print(message, file=sys.stderr)
def error_message(message): def error_message(message_lines):
""" """
Prints an error message for fatal issues Prints an error message for fatal issues. The first line is appended with
'jc: Error - ' and subsequent lines are indented. Wraps text as needed based
on the terminal width.
Parameters: Parameters:
message: (string) text of message message: (list) list of string lines
Returns: Returns:
None - just prints output to STDERR None - just prints output to STDERR
""" """
columns = shutil.get_terminal_size().columns
error_string = f'jc: Error - {message}' first_wrapper = TextWrapper(width=columns, subsequent_indent=' ' * 13)
print(error_string, file=sys.stderr) next_wrapper = TextWrapper(width=columns, initial_indent=' ' * 13,
subsequent_indent=' ' * 13)
first_line = message_lines.pop(0)
first_str = f'jc: Error - {first_line}'
first_str = first_wrapper.fill(first_str)
print(first_str, file=sys.stderr)
for line in message_lines:
if line == '':
continue
message = next_wrapper.fill(line)
print(message, file=sys.stderr)
def compatibility(mod_name, compatible): def compatibility(mod_name, compatible):
@ -64,8 +100,8 @@ def compatibility(mod_name, compatible):
if not platform_found: if not platform_found:
mod = mod_name.split('.')[-1] mod = mod_name.split('.')[-1]
compat_list = ', '.join(compatible) compat_list = ', '.join(compatible)
warning_message(f'{mod} parser not compatible with your OS ({sys.platform}).\n' warning_message([f'{mod} parser not compatible with your OS ({sys.platform}).',
f' Compatible platforms: {compat_list}') f'Compatible platforms: {compat_list}'])
def has_data(data): def has_data(data):