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

Merge pull request #156 from kellyjonbrazil/dev

Dev v1.16.1
This commit is contained in:
Kelly Brazil
2021-08-16 10:32:03 -07:00
committed by GitHub
12 changed files with 52 additions and 15 deletions

View File

@ -1,5 +1,11 @@
jc changelog jc changelog
20210813 v1.16.1
- Note to Package Maintainers: please see note at 20210720 v1.16.0
- Fix issue with process substitution with the magic syntax
- Fix issue with globs not including filenames with spaces with magic syntax
- Fix stat parser to properly handle filenames with spaces on macOS/BSD
20210720 v1.16.0 20210720 v1.16.0
- Note to Package Maintainers: - Note to Package Maintainers:
TL;DR: `/man/jc.1.gz` and `/jc/man/jc.1.gz` are deprecated and only `/man/jc.1` should be used. TL;DR: `/man/jc.1.gz` and `/jc/man/jc.1.gz` are deprecated and only `/man/jc.1` should be used.

View File

@ -193,4 +193,4 @@ Returns:
## Parser Information ## Parser Information
Compatibility: linux, darwin, freebsd Compatibility: linux, darwin, freebsd
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -86,4 +86,4 @@ Module Example:
""" """
name = 'jc' name = 'jc'
__version__ = '1.16.0' __version__ = '1.16.1'

View File

@ -6,10 +6,10 @@ import sys
import os import os
import os.path import os.path
import re import re
import shlex
import importlib import importlib
import textwrap import textwrap
import signal import signal
import shlex
import subprocess import subprocess
import json import json
import jc import jc
@ -360,11 +360,10 @@ def help_doc(options):
# load parser module just in time so we don't need to load all modules # load parser module just in time so we don't need to load all modules
parser = parser_module(arg) parser = parser_module(arg)
compatible = ', '.join(parser.info.compatible) compatible = ', '.join(parser.info.compatible)
doc_text = f'''{parser.__doc__} doc_text = \
Compatibility: {compatible} f'{parser.__doc__}\n'\
f'Compatibility: {compatible}\n\n'\
Version {parser.info.version} by {parser.info.author} ({parser.info.author_email}) f'Version {parser.info.version} by {parser.info.author} ({parser.info.author_email})\n'
'''
return doc_text return doc_text
@ -415,8 +414,7 @@ def magic_parser(args):
if len(args) <= 1 or args[1].startswith('--'): if len(args) <= 1 or args[1].startswith('--'):
return False, None, None, [] return False, None, None, []
# correctly parse escape characters and spaces with shlex args_given = args[1:]
args_given = ' '.join(map(shlex.quote, args[1:])).split()
options = [] options = []
# find the options # find the options
@ -466,7 +464,11 @@ def magic_parser(args):
def run_user_command(command): def run_user_command(command):
"""Use subprocess to run the user's command. Returns the STDOUT, STDERR, and the Exit Code as a tuple.""" """Use subprocess to run the user's command. Returns the STDOUT, STDERR, and the Exit Code as a tuple."""
proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) proc = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=False, # Allows inheriting file descriptors. Useful for process substitution
universal_newlines=True)
stdout, stderr = proc.communicate() stdout, stderr = proc.communicate()
return ( return (
@ -545,7 +547,10 @@ def main():
# if magic syntax used, try to run the command and error if it's not found, etc. # if magic syntax used, try to run the command and error if it's not found, etc.
magic_stdout, magic_stderr, magic_exit_code = None, None, 0 magic_stdout, magic_stderr, magic_exit_code = None, None, 0
if run_command: if run_command:
run_command_str = ' '.join(run_command) try:
run_command_str = shlex.join(run_command) # python 3.8+
except AttributeError:
run_command_str = ' '.join(run_command) # older python versions
if valid_command: if valid_command:
try: try:
@ -560,6 +565,13 @@ def main():
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:
if debug:
raise
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.')
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
except Exception: except Exception:
if debug: if debug:
raise raise

Binary file not shown.

View File

@ -169,7 +169,7 @@ import jc.utils
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.8' version = '1.9'
description = '`stat` command parser' description = '`stat` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -322,7 +322,7 @@ def parse(data, raw=False, quiet=False):
for line in cleandata: for line in cleandata:
value = shlex.split(line) value = shlex.split(line)
output_line = { output_line = {
'file': value[15], 'file': ' '.join(value[15:]),
'unix_device': value[0], 'unix_device': value[0],
'inode': value[1], 'inode': value[1],
'flags': value[2], 'flags': value[2],

View File

@ -1,4 +1,8 @@
<<<<<<< HEAD
.TH jc 1 2021-08-13 1.16.1 "JSON CLI output utility"
=======
.TH jc 1 2021-07-22 1.16.0 "JSON CLI output utility" .TH jc 1 2021-07-22 1.16.0 "JSON CLI output utility"
>>>>>>> master
.SH NAME .SH NAME
jc \- JSONifies the output of many CLI tools and file-types jc \- JSONifies the output of many CLI tools and file-types
.SH SYNOPSIS .SH SYNOPSIS

Binary file not shown.

View File

@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
setuptools.setup( setuptools.setup(
name='jc', name='jc',
version='1.16.0', version='1.16.1',
author='Kelly Brazil', author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com', author_email='kellyjonbrazil@gmail.com',
description='Converts the output of popular command-line tools and file-types to JSON.', description='Converts the output of popular command-line tools and file-types to JSON.',

View File

@ -0,0 +1 @@
[{"file":"file name with spaces.txt","unix_device":16777220,"inode":161929661,"flags":"-rw-r--r--","links":1,"user":"kbrazil","group":"staff","rdev":0,"size":0,"access_time":"Aug 13 15:03:52 2021","modify_time":"Aug 13 14:37:03 2021","change_time":"Aug 13 14:37:03 2021","birth_time":"Aug 13 14:37:03 2021","block_size":4096,"blocks":0,"unix_flags":"0","access_time_epoch":1628892232,"access_time_epoch_utc":null,"modify_time_epoch":1628890623,"modify_time_epoch_utc":null,"change_time_epoch":1628890623,"change_time_epoch_utc":null,"birth_time_epoch":1628890623,"birth_time_epoch_utc":null}]

View File

@ -0,0 +1,2 @@
16777220 161929661 -rw-r--r-- 1 kbrazil staff 0 0 "Aug 13 15:03:52 2021" "Aug 13 14:37:03 2021" "Aug 13 14:37:03 2021" "Aug 13 14:37:03 2021" 4096 0 0 file name with spaces.txt

View File

@ -26,6 +26,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.out'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_stat = f.read() self.osx_10_14_6_stat = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_stat_filename_with_spaces = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.out'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.out'), 'r', encoding='utf-8') as f:
self.freebsd12_stat = f.read() self.freebsd12_stat = f.read()
@ -39,6 +42,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_stat_json = json.loads(f.read()) self.osx_10_14_6_stat_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_stat_filename_with_spaces_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.json'), 'r', encoding='utf-8') as f:
self.freebsd12_stat_json = json.loads(f.read()) self.freebsd12_stat_json = json.loads(f.read())
@ -66,6 +72,12 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.stat.parse(self.osx_10_14_6_stat, quiet=True), self.osx_10_14_6_stat_json) self.assertEqual(jc.parsers.stat.parse(self.osx_10_14_6_stat, quiet=True), self.osx_10_14_6_stat_json)
def test_stat_filename_with_spaces_osx_10_14_6(self):
"""
Test 'stat' filename with spaces on OSX 10.14.6
"""
self.assertEqual(jc.parsers.stat.parse(self.osx_10_14_6_stat_filename_with_spaces, quiet=True), self.osx_10_14_6_stat_filename_with_spaces_json)
def test_stat_freebsd12(self): def test_stat_freebsd12(self):
""" """
Test 'stat /foo/*' on FreeBSD12 Test 'stat /foo/*' on FreeBSD12