1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-13 01:20:24 +02:00

relax JSONDictType - unions and Dicts cause a lot of friction

This commit is contained in:
Kelly Brazil
2022-12-05 12:15:35 -08:00
parent 6f0a53ed02
commit 688a2099b5
6 changed files with 34 additions and 39 deletions

View File

@ -51,7 +51,7 @@ Add `_jc_meta` object to output line if `ignore_exceptions=True`
### stream\_error ### stream\_error
```python ```python
def stream_error(e: BaseException, line: str) -> Dict[str, MetadataType] def stream_error(e: BaseException, line: str) -> JSONDictType
``` ```
Return an error `_jc_meta` field. Return an error `_jc_meta` field.

View File

@ -15,7 +15,7 @@ from .lib import (
__version__, parser_info, all_parser_info, parsers, _get_parser, _parser_is_streaming, __version__, parser_info, all_parser_info, parsers, _get_parser, _parser_is_streaming,
parser_mod_list, standard_parser_mod_list, plugin_parser_mod_list, streaming_parser_mod_list parser_mod_list, standard_parser_mod_list, plugin_parser_mod_list, streaming_parser_mod_list
) )
from .jc_types import JSONDictType, AboutJCType, MetadataType, CustomColorType, ParserInfoType from .jc_types import JSONDictType, CustomColorType, ParserInfoType
from . import utils from . import utils
from .cli_data import ( from .cli_data import (
long_options_map, new_pygments_colors, old_pygments_colors, helptext_preamble_string, long_options_map, new_pygments_colors, old_pygments_colors, helptext_preamble_string,
@ -74,7 +74,7 @@ class JcCli():
def __init__(self) -> None: def __init__(self) -> None:
self.data_in: Optional[Union[str, bytes, TextIO]] = None self.data_in: Optional[Union[str, bytes, TextIO]] = None
self.data_out: Optional[Union[List[JSONDictType], JSONDictType, AboutJCType]] = None self.data_out: Optional[Union[List[JSONDictType], JSONDictType]] = None
self.options: List[str] = [] self.options: List[str] = []
self.args: List[str] = [] self.args: List[str] = []
self.parser_module: Optional[ModuleType] = None self.parser_module: Optional[ModuleType] = None
@ -214,7 +214,7 @@ class JcCli():
return otext return otext
@staticmethod @staticmethod
def about_jc() -> AboutJCType: def about_jc() -> JSONDictType:
"""Return jc info and the contents of each parser.info as a dictionary""" """Return jc info and the contents of each parser.info as a dictionary"""
return { return {
'name': 'jc', 'name': 'jc',
@ -598,7 +598,7 @@ class JcCli():
even if there are no results. even if there are no results.
""" """
if self.run_timestamp: if self.run_timestamp:
meta_obj: MetadataType = { meta_obj: JSONDictType = {
'parser': self.parser_name, 'parser': self.parser_name,
'timestamp': self.run_timestamp.timestamp() 'timestamp': self.run_timestamp.timestamp()
} }
@ -609,9 +609,9 @@ class JcCli():
if isinstance(self.data_out, dict): if isinstance(self.data_out, dict):
if '_jc_meta' not in self.data_out: if '_jc_meta' not in self.data_out:
self.data_out['_jc_meta'] = {} # type: ignore self.data_out['_jc_meta'] = {}
self.data_out['_jc_meta'].update(meta_obj) # type: ignore self.data_out['_jc_meta'].update(meta_obj)
elif isinstance(self.data_out, list): elif isinstance(self.data_out, list):
if not self.data_out: if not self.data_out:
@ -622,7 +622,7 @@ class JcCli():
if '_jc_meta' not in item: if '_jc_meta' not in item:
item['_jc_meta'] = {} item['_jc_meta'] = {}
item['_jc_meta'].update(meta_obj) # type: ignore item['_jc_meta'].update(meta_obj)
else: else:
utils.error_message(['Parser returned an unsupported object type.']) utils.error_message(['Parser returned an unsupported object type.'])

View File

@ -1,11 +1,9 @@
"""jc - JSON Convert lib module""" """jc - JSON Convert lib module"""
import sys import sys
from datetime import datetime from typing import Any, Dict, List, Tuple, Iterator, Optional, Union
from typing import Dict, List, Tuple, Iterator, Optional, Union
JSONDictType = Dict[str, Union[str, int, float, bool, List, Dict, None]] JSONDictType = Dict[str, Any]
MetadataType = Dict[str, Optional[Union[str, int, float, List[str], datetime]]]
StreamingOutputType = Iterator[Union[JSONDictType, Tuple[BaseException, str]]] StreamingOutputType = Iterator[Union[JSONDictType, Tuple[BaseException, str]]]
if sys.version_info >= (3, 8): if sys.version_info >= (3, 8):
@ -45,9 +43,6 @@ else:
TimeStampFormatType = Dict TimeStampFormatType = Dict
AboutJCType = Dict[str, Union[str, int, List[ParserInfoType]]]
try: try:
from pygments.token import (Name, Number, String, Keyword) from pygments.token import (Name, Number, String, Keyword)
CustomColorType = Dict[Union[Name.Tag, Number, String, Keyword], str] CustomColorType = Dict[Union[Name.Tag, Number, String, Keyword], str]

View File

@ -212,7 +212,7 @@ Examples:
""" """
import re import re
from ipaddress import IPv4Network from ipaddress import IPv4Network
from typing import List, Dict from typing import List, Dict, Optional
from jc.jc_types import JSONDictType from jc.jc_types import JSONDictType
import jc.utils import jc.utils
@ -230,7 +230,7 @@ class info():
__version__ = info.version __version__ = info.version
def _convert_cidr_to_quad(string): def _convert_cidr_to_quad(string: str) -> str:
return str(IPv4Network('0.0.0.0/' + string).netmask) return str(IPv4Network('0.0.0.0/' + string).netmask)
@ -261,72 +261,72 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
# convert OSX-style subnet mask to dotted quad # convert OSX-style subnet mask to dotted quad
if 'ipv4_mask' in entry: if 'ipv4_mask' in entry:
try: try:
if entry['ipv4_mask'].startswith('0x'): # type: ignore if entry['ipv4_mask'].startswith('0x'):
new_mask = entry['ipv4_mask'] new_mask = entry['ipv4_mask']
new_mask = new_mask.lstrip('0x') # type: ignore new_mask = new_mask.lstrip('0x')
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)]) new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])
entry['ipv4_mask'] = new_mask entry['ipv4_mask'] = new_mask
except (ValueError, TypeError, AttributeError): except (ValueError, TypeError, AttributeError):
pass pass
# for new-style freebsd output convert CIDR mask to dotted-quad to match other output # for new-style freebsd output convert CIDR mask to dotted-quad to match other output
if entry['ipv4_mask'] and not '.' in entry['ipv4_mask']: # type: ignore if entry['ipv4_mask'] and not '.' in entry['ipv4_mask']:
entry['ipv4_mask'] = _convert_cidr_to_quad(entry['ipv4_mask']) entry['ipv4_mask'] = _convert_cidr_to_quad(entry['ipv4_mask'])
# convert state value to an array # convert state value to an array
if 'state' in entry: if 'state' in entry:
try: try:
new_state = entry['state'].split(',') # type: ignore new_state = entry['state'].split(',')
entry['state'] = new_state entry['state'] = new_state
except (ValueError, TypeError, AttributeError): except (ValueError, TypeError, AttributeError):
pass pass
# conversions for list of ipv4 addresses # conversions for list of ipv4 addresses
if 'ipv4' in entry: if 'ipv4' in entry:
for ip_address in entry['ipv4']: # type: ignore for ip_address in entry['ipv4']:
if 'mask' in ip_address: if 'mask' in ip_address:
try: try:
if ip_address['mask'].startswith('0x'): # type: ignore if ip_address['mask'].startswith('0x'):
new_mask = ip_address['mask'] # type: ignore new_mask = ip_address['mask']
new_mask = new_mask.lstrip('0x') new_mask = new_mask.lstrip('0x')
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)]) new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])
ip_address['mask'] = new_mask # type: ignore ip_address['mask'] = new_mask
except (ValueError, TypeError, AttributeError): except (ValueError, TypeError, AttributeError):
pass pass
# for new-style freebsd output convert CIDR mask to dotted-quad to match other output # for new-style freebsd output convert CIDR mask to dotted-quad to match other output
if ip_address['mask'] and not '.' in ip_address['mask']: # type: ignore if ip_address['mask'] and not '.' in ip_address['mask']:
ip_address['mask'] = _convert_cidr_to_quad(ip_address['mask']) # type: ignore ip_address['mask'] = _convert_cidr_to_quad(ip_address['mask'])
# conversions for list of ipv6 addresses # conversions for list of ipv6 addresses
if 'ipv6' in entry: if 'ipv6' in entry:
for ip_address in entry['ipv6']: # type: ignore for ip_address in entry['ipv6']:
if 'mask' in ip_address: if 'mask' in ip_address:
ip_address['mask'] = jc.utils.convert_to_int(ip_address['mask']) # type: ignore ip_address['mask'] = jc.utils.convert_to_int(ip_address['mask'])
# conversions for list of lanes # conversions for list of lanes
if 'lanes' in entry: if 'lanes' in entry:
for lane_item in entry['lanes']: # type: ignore for lane_item in entry['lanes']:
for key in lane_item: for key in lane_item:
if key in int_list: if key in int_list:
lane_item[key] = jc.utils.convert_to_int(lane_item[key]) # type: ignore lane_item[key] = jc.utils.convert_to_int(lane_item[key])
if key in float_list: if key in float_list:
lane_item[key] = jc.utils.convert_to_float(lane_item[key]) # type: ignore lane_item[key] = jc.utils.convert_to_float(lane_item[key])
# final conversions # final conversions
if entry.get('media_flags', None): if entry.get('media_flags', None):
entry['media_flags'] = entry['media_flags'].split(',') # type: ignore entry['media_flags'] = entry['media_flags'].split(',')
if entry.get('nd6_flags', None): if entry.get('nd6_flags', None):
entry['nd6_flags'] = entry['nd6_flags'].split(',') # type: ignore entry['nd6_flags'] = entry['nd6_flags'].split(',')
if entry.get('options_flags', None): if entry.get('options_flags', None):
entry['options_flags'] = entry['options_flags'].split(',') # type: ignore entry['options_flags'] = entry['options_flags'].split(',')
return proc_data return proc_data
def _bundle_match(pattern_list, string): def _bundle_match(pattern_list: List[re.Pattern], string: str) -> Optional[re.Match]:
"""Returns a match object if a string matches one of a list of patterns. """Returns a match object if a string matches one of a list of patterns.
If no match is found, returns None""" If no match is found, returns None"""
for pattern in pattern_list: for pattern in pattern_list:

View File

@ -2,7 +2,7 @@
from functools import wraps from functools import wraps
from typing import Dict, Tuple, Union, Iterable, Callable, TypeVar, cast, Any from typing import Dict, Tuple, Union, Iterable, Callable, TypeVar, cast, Any
from .jc_types import JSONDictType, MetadataType from .jc_types import JSONDictType
F = TypeVar('F', bound=Callable[..., Any]) F = TypeVar('F', bound=Callable[..., Any])
@ -31,7 +31,7 @@ def stream_success(output_line: JSONDictType, ignore_exceptions: bool) -> JSONDi
return output_line return output_line
def stream_error(e: BaseException, line: str) -> Dict[str, MetadataType]: def stream_error(e: BaseException, line: str) -> JSONDictType:
""" """
Return an error `_jc_meta` field. Return an error `_jc_meta` field.
""" """

View File

@ -1,4 +1,4 @@
.TH jc 1 2022-12-02 1.22.3 "JSON Convert" .TH jc 1 2022-12-05 1.22.3 "JSON Convert"
.SH NAME .SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings
.SH SYNOPSIS .SH SYNOPSIS