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:
@ -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:
|
||||||
|
|
||||||
|
39
jc/cli.py
39
jc/cli.py
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
60
jc/utils.py
60
jc/utils.py
@ -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):
|
||||||
|
Reference in New Issue
Block a user