1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2026-04-24 20:56:11 +02:00

remove int_value field and add tests

This commit is contained in:
Kelly Brazil
2026-03-13 15:16:54 -07:00
parent 1d19de3005
commit 7f2722ff96
13 changed files with 189 additions and 26 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
jc changelog
20260310 v1.25.7
20260313 v1.25.7
- Add `typeset` and `declare` Bash internal command parser to convert variables
simple arrays, and associative arrays along with object metadata
- Enhance `rsync` and `rsync-s` parsers to add `--stats` or `--info=stats[1-3]` fields
+77 -25
View File
@@ -19,9 +19,8 @@ Schema:
[
{
"name": string,
"value": string/array/object/null, # [0]
"int_value": integer/array/object/null, # [1]
"type": string, # [2]
"value": string/integer/array/object/null, # [0]
"type": string, # [1]
"readonly": boolean/null,
"integer": boolean/null,
"lowercase": boolean/null,
@@ -36,28 +35,84 @@ Schema:
If declare options are not given to `jc` within the `typeset` output, then
it will assume all arrays are simple `array` type.
[0] Based on type. `variable` type is always string value when set, null if
not set. `array` type value is an array of strings. `associative` type
value is an object of key/value pairs where values are strings.
Objects have the schema of:
[0] Based on type. `variable` type is null if not set, a string when the
bash variable is set unless the `integer` field is set to `True`, then
the type is integer. `array` type is an array of strings or integers as
above. `associative` type is an object of key/value pairs where values
are strings or integers as above. Objects have the schema of:
{
"<key1>": string,
"<key2>": string
"<key1>": string/integer,
"<key2>": string/integer
}
[1] If the variable is set as `integer` then same as above except values are
integers. This value is set to null if the `integer` flag is not set.
[2] Possible values: `variable`, `array`, or `associative`
[1] Possible values: `variable`, `array`, or `associative`
Examples:
$ typeset | jc --typeset -p
[]
$ typeset -p | jc --typeset -p
[
{
"name": "associative_array",
"value": {
"key2": "abc",
"key3": "1 2 3",
"key1": "hello \"world\""
},
"type": "associative",
"readonly": false,
"integer": false,
"lowercase": false,
"uppercase": false,
"exported": false
},
{
"name": "integers_associative_array",
"value": {
"one": 1,
"two": 500,
"three": 999
},
"type": "associative",
"readonly": false,
"integer": true,
"lowercase": false,
"uppercase": false,
"exported": false
}
]
$ typeset | jc --typeset -p -r
[]
$ typeset -p | jc --typeset -p -r
[
{
"name": "associative_array",
"value": {
"key2": "abc",
"key3": "1 2 3",
"key1": "hello \"world\""
},
"type": "associative",
"readonly": false,
"integer": false,
"lowercase": false,
"uppercase": false,
"exported": false
},
{
"name": "integers_associative_array",
"value": {
"one": "1",
"two": "500",
"three": "999"
},
"type": "associative",
"readonly": false,
"integer": true,
"lowercase": false,
"uppercase": false,
"exported": false
}
]
"""
import shlex
import re
@@ -100,7 +155,7 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
for item in proc_data:
if item['type'] == 'variable' and item['integer']:
item['int_value'] = jc.utils.convert_to_int(item['value'])
item['value'] = jc.utils.convert_to_int(item['value'])
elif item['type'] == 'array' and item['integer'] \
and isinstance(item['value'], list):
@@ -109,7 +164,7 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
for number in item['value']:
new_num_list.append(jc.utils.convert_to_int(number))
item['int_value'] = new_num_list
item['value'] = new_num_list
elif (item['type'] == 'array' and item['integer'] \
and isinstance(item['value'], dict)) \
@@ -119,7 +174,7 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
for key, val in item['value'].items():
new_num_dict.update({key: jc.utils.convert_to_int(val)})
item['int_value'] = new_num_dict
item['value'] = new_num_dict
return proc_data
@@ -141,8 +196,7 @@ def _get_associative_array_vals(body: str) -> Dict[str, str]:
for item in body_split:
key, val = item.split('=', maxsplit=1)
key = _remove_bookends(key, '[', ']')
key_val = {key: val}
values.update(key_val)
values.update({key: val})
return values
@@ -167,8 +221,6 @@ def _get_declare_options(line: str, type_hint: str = 'variable') -> Dict:
declare_opts_match = re.match(DECLARE_OPTS_PATTERN, line)
if declare_opts_match:
for opt in declare_opts_match['options']:
if opt == '-':
continue
if opt in opts_map:
opts[opts_map[opt]] = True
continue
@@ -196,6 +248,7 @@ def _remove_quotes(data: str, remove_char: str ='"') -> str:
return data[1:-1]
return data
def parse(
data: str,
raw: bool = False,
@@ -226,7 +279,6 @@ def parse(
item = {
"name": '',
"value": '',
"int_value": None,
"type": None,
"readonly": None,
"integer": None,
+1
View File
@@ -0,0 +1 @@
[{"name":"BASH_ARGC","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_ARGV","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_LINENO","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_SOURCE","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_VERSINFO","value":["5","3","9","1","release","aarch64-apple-darwin24.6.0"],"type":"array","readonly":true,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"DIRSTACK","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"FUNCNAME","value":null,"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"GROUPS","value":[],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"PIPESTATUS","value":["0"],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"integers_array","value":[1,100,999],"type":"array","readonly":false,"integer":true,"lowercase":false,"uppercase":false,"exported":false},{"name":"simple_array","value":["hello \"world\"","abc","1 2 3"],"type":"array","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"uppercase_array","value":["ABC","123","XYZ"],"type":"array","readonly":true,"integer":false,"lowercase":false,"uppercase":true,"exported":false}]
+12
View File
@@ -0,0 +1,12 @@
declare -a BASH_ARGC=()
declare -a BASH_ARGV=()
declare -a BASH_LINENO=()
declare -a BASH_SOURCE=()
declare -ar BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="aarch64-apple-darwin24.6.0")
declare -a DIRSTACK=()
declare -a FUNCNAME
declare -a GROUPS=()
declare -a PIPESTATUS=([0]="0")
declare -ai integers_array=([0]="1" [1]="100" [2]="999")
declare -a simple_array=([0]="hello \"world\"" [1]="abc" [2]="1 2 3")
declare -aru uppercase_array=([0]="ABC" [1]="123" [2]="XYZ")
+1
View File
@@ -0,0 +1 @@
[{"name":"BASH_ALIASES","value":[],"type":"associative","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_CMDS","value":[],"type":"associative","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"associative_array","value":{"key2":"abc","key3":"1 2 3","key1":"hello \"world\""},"type":"associative","readonly":false,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"integers_associative_array","value":{"one":1,"two":500,"three":999},"type":"associative","readonly":false,"integer":true,"lowercase":false,"uppercase":false,"exported":false}]
+4
View File
@@ -0,0 +1,4 @@
declare -A BASH_ALIASES=()
declare -A BASH_CMDS=()
declare -A associative_array=([key2]="abc" [key3]="1 2 3" [key1]="hello \"world\"" )
declare -Ai integers_associative_array=([one]="1" [two]="500" [three]="999" )
File diff suppressed because one or more lines are too long
+32
View File
@@ -0,0 +1,32 @@
declare -- BASH="/opt/homebrew/bin/bash"
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath"
declare -i BASHPID
declare -A BASH_ALIASES=()
declare -a BASH_ARGC=()
declare -- BASH_ARGV0
declare -- BASH_LOADABLES_PATH="/opt/homebrew/lib/bash:/usr/local/lib/bash:/usr/lib/bash:/opt/local/lib/bash:/usr/pkg/lib/bash:/opt/pkg/lib/bash:."
declare -ar BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="aarch64-apple-darwin24.6.0")
declare -- COLUMNS="92"
declare -ir EUID="501"
declare -a FUNCNAME
declare -i HISTCMD
declare -x HOME="/Users/kbrazil"
declare -- IFS=$' \t\n'
declare -x JC_COLORS="cyan,default,default,default"
declare -x OLDPWD
declare -a PIPESTATUS=([0]="0")
declare -ir PPID="50074"
declare -- PS1="\\s-\\v\\\$ "
declare -- PS2="> "
declare -- PS4="+ "
declare -i RANDOM
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -- _="-p"
declare -x __CFBundleIdentifier="com.apple.Terminal"
declare -ai integers_array=([0]="1" [1]="100" [2]="999")
declare -a simple_array=([0]="hello \"world\"" [1]="abc" [2]="1 2 3")
declare -r readonly_var="hello"
declare -aru uppercase_array=([0]="ABC" [1]="123" [2]="XYZ")
declare -a num_string_array=([0]="1" [1]="2" [2]="3")
declare -A associative_array=([key2]="abc" [key3]="1 2 3" [key1]="hello \"world\"" )
declare -Ai integers_associative_array=([one]="1" [two]="500" [three]="999" )
+1
View File
@@ -0,0 +1 @@
[{"name":"BASHOPTS","value":"checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"BASH_ALIASES","value":[],"type":"array","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"BASH_VERSINFO","value":["5","3","9","1","release","aarch64-apple-darwin24.6.0"],"type":"array","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"BASH_VERSION","value":"'5.3.9(1)-release'","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"IFS","value":"$' \\t\\n'","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"INFOPATH","value":"/opt/homebrew/share/info:","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"JC_COLORS","value":"cyan,default,default,default","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"PS1","value":"'\\s-\\v\\$ '","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"PS2","value":"'> '","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"PS4","value":"'+ '","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"TERM_PROGRAM_VERSION","value":"455.1","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"TERM_SESSION_ID","value":"E5896C5D-9C9A-4178-9246-00158A3F832F","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"XPC_FLAGS","value":"0x0","type":"variable","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"associative_array","value":{"key2":"abc","key3":"1 2 3","key1":"hello \"world\""},"type":"associative","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"integers_array","value":["1","100","999"],"type":"array","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"simple_array","value":["hello \"world\"","abc","1 2 3"],"type":"array","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null},{"name":"uppercase_array","value":["ABC","123","XYZ"],"type":"array","readonly":null,"integer":null,"lowercase":null,"uppercase":null,"exported":null}]
+19
View File
@@ -0,0 +1,19 @@
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="aarch64-apple-darwin24.6.0")
BASH_VERSION='5.3.9(1)-release'
COLUMNS=92
IFS=$' \t\n'
INFOPATH=/opt/homebrew/share/info:
JC_COLORS=cyan,default,default,default
PS1='\s-\v\$ '
PS2='> '
PS4='+ '
TERM_PROGRAM_VERSION=455.1
TERM_SESSION_ID=E5896C5D-9C9A-4178-9246-00158A3F832F
XPC_FLAGS=0x0
_=-a
associative_array=([key2]="abc" [key3]="1 2 3" [key1]="hello \"world\"" )
integers_array=([0]="1" [1]="100" [2]="999")
simple_array=([0]="hello \"world\"" [1]="abc" [2]="1 2 3")
uppercase_array=([0]="ABC" [1]="123" [2]="XYZ")
+1
View File
@@ -0,0 +1 @@
[{"name":"BASHOPTS","value":"checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath","type":"variable","readonly":true,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"BASH_VERSINFO","value":["5","3","9","1","release","aarch64-apple-darwin24.6.0"],"type":"array","readonly":true,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"EUID","value":501,"type":"variable","readonly":true,"integer":true,"lowercase":false,"uppercase":false,"exported":false},{"name":"PPID","value":50074,"type":"variable","readonly":true,"integer":true,"lowercase":false,"uppercase":false,"exported":false},{"name":"SHELLOPTS","value":"braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor","type":"variable","readonly":true,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"UID","value":501,"type":"variable","readonly":true,"integer":true,"lowercase":false,"uppercase":false,"exported":false},{"name":"readonly_var","value":"hello","type":"variable","readonly":true,"integer":false,"lowercase":false,"uppercase":false,"exported":false},{"name":"uppercase_array","value":["ABC","123","XYZ"],"type":"array","readonly":true,"integer":false,"lowercase":false,"uppercase":true,"exported":false}]
+8
View File
@@ -0,0 +1,8 @@
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath"
declare -ar BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="aarch64-apple-darwin24.6.0")
declare -ir EUID="501"
declare -ir PPID="50074"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="501"
declare -r readonly_var="hello"
declare -aru uppercase_array=([0]="ABC" [1]="123" [2]="XYZ")
+31
View File
@@ -0,0 +1,31 @@
import unittest
import os
import sys
sys.path.append(os.getcwd())
from tests import utils_for_test as test_utils
sys.path.pop()
# Execute these steps for standard tests:
# - Save this file as `test_{parser_name}.py` since the helper methods extract parser names from the filename.
# - Organize fixtures in `tests/fixtures` for optimal structure.
# - Format fixtures as follows (using double dashes):
# - `{parser_name}--{some_test_description}.out` for command output.
# - `{parser_name}--{some_test_description}.json` for expected JSON after parsing.
class MyTests(unittest.TestCase):
def test_foo_nodata(self):
"""
Test 'foo' with no data
"""
test_utils.run_no_data(self, __file__, [])
def test_foo_all_fixtures(self):
"""
Test 'foo' with various fixtures
"""
test_utils.run_all_fixtures(self, __file__)
if __name__ == '__main__':
unittest.main()