mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-07-13 01:20:24 +02:00
Merge branch 'dev' into arp_aix
This commit is contained in:
@ -1,13 +1,14 @@
|
|||||||
jc changelog
|
jc changelog
|
||||||
|
|
||||||
20230103 v1.22.5
|
20230105 v1.22.5
|
||||||
- Add TOML parser
|
- Add TOML parser
|
||||||
- Update copyright dates
|
- Add AIX support for the `mount` command parser
|
||||||
- Fix `lsusb` parser when extra hub port status information is output
|
- Fix `lsusb` parser when extra hub port status information is output
|
||||||
- Refactor `lsusb` parser for more code reuse
|
- Refactor `lsusb` parser for more code reuse
|
||||||
- Fix INI parser to include top-level values with no section header
|
- Fix INI parser to include top-level values with no section header
|
||||||
- Fix INI and Key/Value parsers to only remove one quotation mark from the
|
- Fix INI and Key/Value parsers to only remove one quotation mark from the
|
||||||
beginning and end of values.
|
beginning and end of values.
|
||||||
|
- Update copyright dates
|
||||||
|
|
||||||
20221230 v1.22.4
|
20221230 v1.22.4
|
||||||
- Add `iwconfig` command parser
|
- Add `iwconfig` command parser
|
||||||
|
@ -11,10 +11,6 @@ Parses standard `INI` files.
|
|||||||
- Comment prefix can be `#` or `;`. Comments must be on their own line.
|
- Comment prefix can be `#` or `;`. Comments must be on their own line.
|
||||||
- If duplicate keys are found, only the last value will be used.
|
- If duplicate keys are found, only the last value will be used.
|
||||||
|
|
||||||
> Note: If there is no top-level section identifier, then this parser will
|
|
||||||
> add a key named `_top_level_section_` with the top-level key/values
|
|
||||||
> included.
|
|
||||||
|
|
||||||
> Note: The section identifier `[DEFAULT]` is special and provides default
|
> Note: The section identifier `[DEFAULT]` is special and provides default
|
||||||
> values for the section keys that follow. To disable this behavior you must
|
> values for the section keys that follow. To disable this behavior you must
|
||||||
> rename the `[DEFAULT]` section identifier to something else before
|
> rename the `[DEFAULT]` section identifier to something else before
|
||||||
@ -47,34 +43,28 @@ standard library documentation for more details.
|
|||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ cat example.ini
|
$ cat example.ini
|
||||||
[DEFAULT]
|
foo = bar
|
||||||
ServerAliveInterval = 45
|
baz = buz
|
||||||
Compression = yes
|
|
||||||
CompressionLevel = 9
|
|
||||||
ForwardX11 = yes
|
|
||||||
|
|
||||||
[bitbucket.org]
|
[section1]
|
||||||
User = hg
|
key1 = value1
|
||||||
|
key2 = value2
|
||||||
|
|
||||||
[topsecret.server.com]
|
[section2]
|
||||||
Port = 50022
|
key1 = value1
|
||||||
ForwardX11 = no
|
key2 = value2
|
||||||
|
|
||||||
$ cat example.ini | jc --ini -p
|
$ cat example.ini | jc --ini -p
|
||||||
{
|
{
|
||||||
"bitbucket.org": {
|
"foo": "bar",
|
||||||
"ServerAliveInterval": "45",
|
"baz": "buz",
|
||||||
"Compression": "yes",
|
"section1": {
|
||||||
"CompressionLevel": "9",
|
"key1": "value1",
|
||||||
"ForwardX11": "yes",
|
"key2": "value2"
|
||||||
"User": "hg"
|
|
||||||
},
|
},
|
||||||
"topsecret.server.com": {
|
"section2": {
|
||||||
"ServerAliveInterval": "45",
|
"key1": "value1",
|
||||||
"Compression": "yes",
|
"key2": "value2"
|
||||||
"CompressionLevel": "9",
|
|
||||||
"ForwardX11": "no",
|
|
||||||
"Port": "50022"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
docs/parsers/toml.md
Normal file
81
docs/parsers/toml.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||||
|
<a id="jc.parsers.toml"></a>
|
||||||
|
|
||||||
|
# jc.parsers.toml
|
||||||
|
|
||||||
|
jc - JSON Convert TOML file parser
|
||||||
|
|
||||||
|
Usage (cli):
|
||||||
|
|
||||||
|
$ cat file.toml | jc --toml
|
||||||
|
|
||||||
|
Usage (module):
|
||||||
|
|
||||||
|
import jc
|
||||||
|
result = jc.parse('toml', toml_file_output)
|
||||||
|
|
||||||
|
Schema:
|
||||||
|
|
||||||
|
TOML Document converted to a Dictionary.
|
||||||
|
See https://toml.io/en/ for details.
|
||||||
|
|
||||||
|
{
|
||||||
|
"key1": string/int/float/boolean/null/array/object,
|
||||||
|
"key2": string/int/float/boolean/null/array/object
|
||||||
|
}
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
$ cat file.toml
|
||||||
|
title = "TOML Example"
|
||||||
|
|
||||||
|
[owner]
|
||||||
|
name = "Tom Preston-Werner"
|
||||||
|
dob = 1979-05-27T07:32:00-08:00
|
||||||
|
|
||||||
|
[database]
|
||||||
|
enabled = true
|
||||||
|
ports = [ 8000, 8001, 8002 ]
|
||||||
|
|
||||||
|
$ cat file.toml | jc --toml -p
|
||||||
|
{
|
||||||
|
"title": "TOML Example",
|
||||||
|
"owner": {
|
||||||
|
"name": "Tom Preston-Werner",
|
||||||
|
"dob": 296667120,
|
||||||
|
"dob_iso": "1979-05-27T07:32:00-08:00"
|
||||||
|
},
|
||||||
|
"database": {
|
||||||
|
"enabled": true,
|
||||||
|
"ports": [
|
||||||
|
8000,
|
||||||
|
8001,
|
||||||
|
8002
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<a id="jc.parsers.toml.parse"></a>
|
||||||
|
|
||||||
|
### parse
|
||||||
|
|
||||||
|
```python
|
||||||
|
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
|
||||||
|
```
|
||||||
|
|
||||||
|
Main text parsing function
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
data: (string) text data to parse
|
||||||
|
raw: (boolean) unprocessed output if True
|
||||||
|
quiet: (boolean) suppress warning messages if True
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
Dictionary. Raw or processed structured data.
|
||||||
|
|
||||||
|
### Parser Information
|
||||||
|
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||||
|
|
||||||
|
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
@ -18,8 +18,8 @@ Usage (module):
|
|||||||
|
|
||||||
Schema:
|
Schema:
|
||||||
|
|
||||||
YAML Document converted to a Dictionary
|
YAML Document converted to a Dictionary.
|
||||||
See https://pypi.org/project/ruamel.yaml for details
|
See https://pypi.org/project/ruamel.yaml for details.
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ Schema:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ cat istio-mtls-permissive.yaml
|
$ cat file.yaml
|
||||||
apiVersion: "authentication.istio.io/v1alpha1"
|
apiVersion: "authentication.istio.io/v1alpha1"
|
||||||
kind: "Policy"
|
kind: "Policy"
|
||||||
metadata:
|
metadata:
|
||||||
@ -51,7 +51,7 @@ Examples:
|
|||||||
tls:
|
tls:
|
||||||
mode: ISTIO_MUTUAL
|
mode: ISTIO_MUTUAL
|
||||||
|
|
||||||
$ cat istio-mtls-permissive.yaml | jc --yaml -p
|
$ cat file.yaml | jc --yaml -p
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"apiVersion": "authentication.istio.io/v1alpha1",
|
"apiVersion": "authentication.istio.io/v1alpha1",
|
||||||
|
@ -99,4 +99,4 @@ Returns:
|
|||||||
### Parser Information
|
### Parser Information
|
||||||
Compatibility: linux, darwin
|
Compatibility: linux, darwin
|
||||||
|
|
||||||
Version 1.1 by Matt J (https://github.com/listuser)
|
Version 1.2 by Matt J (https://github.com/listuser)
|
||||||
|
@ -6,10 +6,6 @@ Parses standard `INI` files.
|
|||||||
- Comment prefix can be `#` or `;`. Comments must be on their own line.
|
- Comment prefix can be `#` or `;`. Comments must be on their own line.
|
||||||
- If duplicate keys are found, only the last value will be used.
|
- If duplicate keys are found, only the last value will be used.
|
||||||
|
|
||||||
> Note: If there is no top-level section identifier, then this parser will
|
|
||||||
> add a key named `_top_level_section_` with the top-level key/values
|
|
||||||
> included.
|
|
||||||
|
|
||||||
> Note: The section identifier `[DEFAULT]` is special and provides default
|
> Note: The section identifier `[DEFAULT]` is special and provides default
|
||||||
> values for the section keys that follow. To disable this behavior you must
|
> values for the section keys that follow. To disable this behavior you must
|
||||||
> rename the `[DEFAULT]` section identifier to something else before
|
> rename the `[DEFAULT]` section identifier to something else before
|
||||||
@ -42,39 +38,34 @@ standard library documentation for more details.
|
|||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ cat example.ini
|
$ cat example.ini
|
||||||
[DEFAULT]
|
foo = bar
|
||||||
ServerAliveInterval = 45
|
baz = buz
|
||||||
Compression = yes
|
|
||||||
CompressionLevel = 9
|
|
||||||
ForwardX11 = yes
|
|
||||||
|
|
||||||
[bitbucket.org]
|
[section1]
|
||||||
User = hg
|
key1 = value1
|
||||||
|
key2 = value2
|
||||||
|
|
||||||
[topsecret.server.com]
|
[section2]
|
||||||
Port = 50022
|
key1 = value1
|
||||||
ForwardX11 = no
|
key2 = value2
|
||||||
|
|
||||||
$ cat example.ini | jc --ini -p
|
$ cat example.ini | jc --ini -p
|
||||||
{
|
{
|
||||||
"bitbucket.org": {
|
"foo": "bar",
|
||||||
"ServerAliveInterval": "45",
|
"baz": "buz",
|
||||||
"Compression": "yes",
|
"section1": {
|
||||||
"CompressionLevel": "9",
|
"key1": "value1",
|
||||||
"ForwardX11": "yes",
|
"key2": "value2"
|
||||||
"User": "hg"
|
|
||||||
},
|
},
|
||||||
"topsecret.server.com": {
|
"section2": {
|
||||||
"ServerAliveInterval": "45",
|
"key1": "value1",
|
||||||
"Compression": "yes",
|
"key2": "value2"
|
||||||
"CompressionLevel": "9",
|
|
||||||
"ForwardX11": "no",
|
|
||||||
"Port": "50022"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
import jc.utils
|
import jc.utils
|
||||||
import configparser
|
import configparser
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
class info():
|
class info():
|
||||||
@ -91,6 +82,19 @@ class info():
|
|||||||
__version__ = info.version
|
__version__ = info.version
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_quotes(value):
|
||||||
|
if value is None:
|
||||||
|
value = ''
|
||||||
|
|
||||||
|
elif value.startswith('"') and value.endswith('"'):
|
||||||
|
value = value[1:-1]
|
||||||
|
|
||||||
|
elif value.startswith("'") and value.endswith("'"):
|
||||||
|
value = value[1:-1]
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def _process(proc_data):
|
def _process(proc_data):
|
||||||
"""
|
"""
|
||||||
Final processing to conform to the schema.
|
Final processing to conform to the schema.
|
||||||
@ -104,16 +108,13 @@ def _process(proc_data):
|
|||||||
Dictionary representing the INI file.
|
Dictionary representing the INI file.
|
||||||
"""
|
"""
|
||||||
# remove quotation marks from beginning and end of values
|
# remove quotation marks from beginning and end of values
|
||||||
for heading in proc_data:
|
for k, v in proc_data.items():
|
||||||
for key, value in proc_data[heading].items():
|
if isinstance(v, dict):
|
||||||
if value is not None and value.startswith('"') and value.endswith('"'):
|
for key, value in v.items():
|
||||||
proc_data[heading][key] = value[1:-1]
|
v[key] = _remove_quotes(value)
|
||||||
|
continue
|
||||||
|
|
||||||
elif value is not None and value.startswith("'") and value.endswith("'"):
|
proc_data[k] = _remove_quotes(v)
|
||||||
proc_data[heading][key] = value[1:-1]
|
|
||||||
|
|
||||||
elif value is None:
|
|
||||||
proc_data[heading][key] = ''
|
|
||||||
|
|
||||||
return proc_data
|
return proc_data
|
||||||
|
|
||||||
@ -153,11 +154,21 @@ def parse(data, raw=False, quiet=False):
|
|||||||
raw_output = {s: dict(ini_parser.items(s)) for s in ini_parser.sections()}
|
raw_output = {s: dict(ini_parser.items(s)) for s in ini_parser.sections()}
|
||||||
|
|
||||||
except configparser.MissingSectionHeaderError:
|
except configparser.MissingSectionHeaderError:
|
||||||
data = '[_top_level_section_]\n' + data
|
# find a top-level section name that will not collide with any existing ones
|
||||||
ini_parser.read_string(data)
|
while True:
|
||||||
raw_output = {s: dict(ini_parser.items(s)) for s in ini_parser.sections()}
|
my_uuid = str(uuid.uuid4())
|
||||||
|
if my_uuid not in data:
|
||||||
|
break
|
||||||
|
|
||||||
|
data = f'[{my_uuid}]\n' + data
|
||||||
|
ini_parser.read_string(data)
|
||||||
|
temp_dict = {s: dict(ini_parser.items(s)) for s in ini_parser.sections()}
|
||||||
|
|
||||||
|
# move items under fake top-level sections to the root
|
||||||
|
raw_output = temp_dict.pop(my_uuid)
|
||||||
|
|
||||||
|
# get the rest of the sections
|
||||||
|
raw_output.update(temp_dict)
|
||||||
|
|
||||||
|
return raw_output if raw else _process(raw_output)
|
||||||
|
|
||||||
if raw:
|
|
||||||
return raw_output
|
|
||||||
else:
|
|
||||||
return _process(raw_output)
|
|
||||||
|
@ -82,15 +82,15 @@ def _process(proc_data):
|
|||||||
"""
|
"""
|
||||||
# remove quotation marks from beginning and end of values
|
# remove quotation marks from beginning and end of values
|
||||||
for key in proc_data:
|
for key in proc_data:
|
||||||
if proc_data[key] is not None and proc_data[key].startswith('"') and proc_data[key].endswith('"'):
|
if proc_data[key] is None:
|
||||||
proc_data[key] = proc_data[key][1:-1]
|
|
||||||
|
|
||||||
elif proc_data[key] is not None and proc_data[key].startswith("'") and proc_data[key].endswith("'"):
|
|
||||||
proc_data[key] = proc_data[key][1:-1]
|
|
||||||
|
|
||||||
elif proc_data[key] is None:
|
|
||||||
proc_data[key] = ''
|
proc_data[key] = ''
|
||||||
|
|
||||||
|
elif proc_data[key].startswith('"') and proc_data[key].endswith('"'):
|
||||||
|
proc_data[key] = proc_data[key][1:-1]
|
||||||
|
|
||||||
|
elif proc_data[key].startswith("'") and proc_data[key].endswith("'"):
|
||||||
|
proc_data[key] = proc_data[key][1:-1]
|
||||||
|
|
||||||
return proc_data
|
return proc_data
|
||||||
|
|
||||||
|
|
||||||
@ -130,8 +130,5 @@ def parse(data, raw=False, quiet=False):
|
|||||||
for key, value in output_dict['data'].items():
|
for key, value in output_dict['data'].items():
|
||||||
raw_output[key] = value
|
raw_output[key] = value
|
||||||
|
|
||||||
if raw:
|
return raw_output if raw else _process(raw_output)
|
||||||
return raw_output
|
|
||||||
else:
|
|
||||||
return _process(raw_output)
|
|
||||||
|
|
||||||
|
@ -341,6 +341,7 @@ class _root_obj:
|
|||||||
|
|
||||||
if '_state' in item[keyname] and item[keyname]['_state']['bus_idx'] == bus_idx:
|
if '_state' in item[keyname] and item[keyname]['_state']['bus_idx'] == bus_idx:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _update_output(self, bus_idx, output_line):
|
def _update_output(self, bus_idx, output_line):
|
||||||
@ -370,7 +371,8 @@ class _descriptor_obj:
|
|||||||
self.list = []
|
self.list = []
|
||||||
|
|
||||||
def _entries_for_this_bus_and_interface_idx_exist(self, bus_idx, iface_idx):
|
def _entries_for_this_bus_and_interface_idx_exist(self, bus_idx, iface_idx):
|
||||||
"""Returns true if there are object entries for the corresponding bus index and interface index"""
|
"""Returns true if there are object entries for the corresponding bus index
|
||||||
|
and interface index"""
|
||||||
for item in self.list:
|
for item in self.list:
|
||||||
keyname = tuple(item.keys())[0]
|
keyname = tuple(item.keys())[0]
|
||||||
|
|
||||||
@ -378,11 +380,12 @@ class _descriptor_obj:
|
|||||||
and item[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
|
and item[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _update_output(self, bus_idx, iface_idx, output_line):
|
def _update_output(self, bus_idx, iface_idx, output_line):
|
||||||
"""modifies output_line dictionary for the corresponding bus index and interface index.
|
"""modifies output_line dictionary for the corresponding bus index and
|
||||||
output_line is the i_desc_obj object."""
|
interface index. output_line is the i_desc_obj object."""
|
||||||
for item in self.list:
|
for item in self.list:
|
||||||
keyname = tuple(item.keys())[0]
|
keyname = tuple(item.keys())[0]
|
||||||
|
|
||||||
@ -409,7 +412,8 @@ class _descriptor_list:
|
|||||||
self.list = []
|
self.list = []
|
||||||
|
|
||||||
def _entries_for_this_bus_and_interface_idx_exist(self, bus_idx, iface_idx):
|
def _entries_for_this_bus_and_interface_idx_exist(self, bus_idx, iface_idx):
|
||||||
"""Returns true if there are object entries for the corresponding bus index and interface index"""
|
"""Returns true if there are object entries for the corresponding bus index
|
||||||
|
and interface index"""
|
||||||
for item in self.list:
|
for item in self.list:
|
||||||
keyname = tuple(item.keys())[0]
|
keyname = tuple(item.keys())[0]
|
||||||
|
|
||||||
@ -417,10 +421,12 @@ class _descriptor_list:
|
|||||||
and item[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
|
and item[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_objects_list(self, bus_idx, iface_idx):
|
def _get_objects_list(self, bus_idx, iface_idx):
|
||||||
"""Returns a list of descriptor object dictionaries for the corresponding bus index and interface index"""
|
"""Returns a list of descriptor object dictionaries for the corresponding
|
||||||
|
bus index and interface index"""
|
||||||
object_collection = []
|
object_collection = []
|
||||||
|
|
||||||
# find max number of items in this object that match the bus_idx and iface_idx
|
# find max number of items in this object that match the bus_idx and iface_idx
|
||||||
@ -458,6 +464,7 @@ class _descriptor_list:
|
|||||||
del item[keyname]['_state']
|
del item[keyname]['_state']
|
||||||
|
|
||||||
object_collection.append(this_object)
|
object_collection.append(this_object)
|
||||||
|
|
||||||
return object_collection
|
return object_collection
|
||||||
|
|
||||||
|
|
||||||
@ -489,7 +496,6 @@ class _LsUsb():
|
|||||||
self.configuration_descriptor = _root_obj('configuration_descriptor')
|
self.configuration_descriptor = _root_obj('configuration_descriptor')
|
||||||
self.interface_association = _root_obj('interface_association')
|
self.interface_association = _root_obj('interface_association')
|
||||||
self.interface_descriptor_list = []
|
self.interface_descriptor_list = []
|
||||||
self.interface_descriptor_attribute_list = []
|
|
||||||
self.cdc_header = _descriptor_obj('cdc_header')
|
self.cdc_header = _descriptor_obj('cdc_header')
|
||||||
self.cdc_call_management = _descriptor_obj('cdc_call_management')
|
self.cdc_call_management = _descriptor_obj('cdc_call_management')
|
||||||
self.cdc_acm = _descriptor_obj('cdc_acm')
|
self.cdc_acm = _descriptor_obj('cdc_acm')
|
||||||
@ -498,7 +504,7 @@ class _LsUsb():
|
|||||||
self.videocontrol_interface_descriptors = _descriptor_list('videocontrol_interface_descriptor')
|
self.videocontrol_interface_descriptors = _descriptor_list('videocontrol_interface_descriptor')
|
||||||
self.videostreaming_interface_descriptors = _descriptor_list('videostreaming_interface_descriptor')
|
self.videostreaming_interface_descriptors = _descriptor_list('videostreaming_interface_descriptor')
|
||||||
self.hid_device_descriptor = _descriptor_obj('hid_device_descriptor')
|
self.hid_device_descriptor = _descriptor_obj('hid_device_descriptor')
|
||||||
self.report_descriptors_list = []
|
# self.report_descriptors_list = [] # not implemented
|
||||||
self.hub_descriptor = _root_obj('hub_descriptor')
|
self.hub_descriptor = _root_obj('hub_descriptor')
|
||||||
self.hub_port_status_list = []
|
self.hub_port_status_list = []
|
||||||
self.device_qualifier_list = []
|
self.device_qualifier_list = []
|
||||||
@ -628,7 +634,7 @@ class _LsUsb():
|
|||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# This section is a list, so need to update indexes
|
# These sections are lists, so need to update indexes
|
||||||
if line.startswith(' Interface Descriptor:'):
|
if line.startswith(' Interface Descriptor:'):
|
||||||
self.section = 'interface_descriptor'
|
self.section = 'interface_descriptor'
|
||||||
self.interface_descriptor_idx += 1
|
self.interface_descriptor_idx += 1
|
||||||
@ -638,21 +644,18 @@ class _LsUsb():
|
|||||||
self.attribute_value = False
|
self.attribute_value = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# This section is a list, so need to update the index
|
|
||||||
if line.startswith(' Endpoint Descriptor:'):
|
if line.startswith(' Endpoint Descriptor:'):
|
||||||
self.section = 'endpoint_descriptor'
|
self.section = 'endpoint_descriptor'
|
||||||
self.endpoint_descriptor_idx += 1
|
self.endpoint_descriptor_idx += 1
|
||||||
self.attribute_value = False
|
self.attribute_value = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# This section is a list, so need to update the index
|
|
||||||
if line.startswith(' VideoControl Interface Descriptor:'):
|
if line.startswith(' VideoControl Interface Descriptor:'):
|
||||||
self.section = 'videocontrol_interface_descriptor'
|
self.section = 'videocontrol_interface_descriptor'
|
||||||
self.videocontrol_interface_descriptor_idx += 1
|
self.videocontrol_interface_descriptor_idx += 1
|
||||||
self.attribute_value = False
|
self.attribute_value = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# This section is a list, so need to update the index
|
|
||||||
if line.startswith(' VideoStreaming Interface Descriptor:'):
|
if line.startswith(' VideoStreaming Interface Descriptor:'):
|
||||||
self.section = 'videostreaming_interface_descriptor'
|
self.section = 'videostreaming_interface_descriptor'
|
||||||
self.videostreaming_interface_descriptor_idx += 1
|
self.videostreaming_interface_descriptor_idx += 1
|
||||||
@ -711,7 +714,7 @@ class _LsUsb():
|
|||||||
'cdc_acm': self.cdc_acm.list,
|
'cdc_acm': self.cdc_acm.list,
|
||||||
'cdc_union': self.cdc_union.list,
|
'cdc_union': self.cdc_union.list,
|
||||||
'hid_device_descriptor': self.hid_device_descriptor.list,
|
'hid_device_descriptor': self.hid_device_descriptor.list,
|
||||||
'report_descriptors': self.report_descriptors_list,
|
# 'report_descriptors': self.report_descriptors_list, # not implemented
|
||||||
'videocontrol_interface_descriptor': self.videocontrol_interface_descriptors.list,
|
'videocontrol_interface_descriptor': self.videocontrol_interface_descriptors.list,
|
||||||
'videostreaming_interface_descriptor': self.videostreaming_interface_descriptors.list,
|
'videostreaming_interface_descriptor': self.videostreaming_interface_descriptors.list,
|
||||||
'endpoint_descriptor': self.endpoint_descriptors.list,
|
'endpoint_descriptor': self.endpoint_descriptors.list,
|
||||||
@ -771,17 +774,15 @@ class _LsUsb():
|
|||||||
del item['_state']
|
del item['_state']
|
||||||
self.output_line.update(item)
|
self.output_line.update(item)
|
||||||
|
|
||||||
# add device_descriptor key
|
# add initial root-level keys
|
||||||
if self.device_descriptor._entries_for_this_bus_exist(idx):
|
if self.device_descriptor._entries_for_this_bus_exist(idx):
|
||||||
self.device_descriptor._update_output(idx, self.output_line)
|
self.device_descriptor._update_output(idx, self.output_line)
|
||||||
|
|
||||||
# add configuration_descriptor key
|
|
||||||
if self.configuration_descriptor._entries_for_this_bus_exist(idx):
|
if self.configuration_descriptor._entries_for_this_bus_exist(idx):
|
||||||
self.configuration_descriptor._update_output(
|
self.configuration_descriptor._update_output(
|
||||||
idx, self.output_line['device_descriptor']
|
idx, self.output_line['device_descriptor']
|
||||||
)
|
)
|
||||||
|
|
||||||
# add interface_association key
|
|
||||||
if self.interface_association._entries_for_this_bus_exist(idx):
|
if self.interface_association._entries_for_this_bus_exist(idx):
|
||||||
self.interface_association._update_output(
|
self.interface_association._update_output(
|
||||||
idx, self.output_line['device_descriptor']['configuration_descriptor']
|
idx, self.output_line['device_descriptor']['configuration_descriptor']
|
||||||
@ -812,7 +813,6 @@ class _LsUsb():
|
|||||||
for iface_idx in range(i_desc_iters + 1):
|
for iface_idx in range(i_desc_iters + 1):
|
||||||
i_desc_obj = _NestedDict()
|
i_desc_obj = _NestedDict()
|
||||||
|
|
||||||
## interface_descriptor_list _root object?
|
|
||||||
for iface_attrs in self.interface_descriptor_list:
|
for iface_attrs in self.interface_descriptor_list:
|
||||||
keyname = tuple(iface_attrs.keys())[0]
|
keyname = tuple(iface_attrs.keys())[0]
|
||||||
|
|
||||||
@ -834,28 +834,19 @@ class _LsUsb():
|
|||||||
del iface_attrs[keyname]['_state']
|
del iface_attrs[keyname]['_state']
|
||||||
i_desc_obj.update(iface_attrs)
|
i_desc_obj.update(iface_attrs)
|
||||||
|
|
||||||
# add cdc_header key if it doesn't exist and there are
|
# add the rest of the interface descriptor keys to the object
|
||||||
# entries for this interface_descriptor
|
|
||||||
if self.cdc_header._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.cdc_header._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
self.cdc_header._update_output(idx, iface_idx, i_desc_obj)
|
self.cdc_header._update_output(idx, iface_idx, i_desc_obj)
|
||||||
|
|
||||||
# add cdc_call_management key if it doesn't exist and there are
|
|
||||||
# entries for this interface_descriptor
|
|
||||||
if self.cdc_call_management._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.cdc_call_management._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
self.cdc_call_management._update_output(idx, iface_idx, i_desc_obj)
|
self.cdc_call_management._update_output(idx, iface_idx, i_desc_obj)
|
||||||
|
|
||||||
# add cdc_acm key if it doesn't exist and there are entries for
|
|
||||||
# this interface_descriptor
|
|
||||||
if self.cdc_acm._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.cdc_acm._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
self.cdc_acm._update_output(idx, iface_idx, i_desc_obj)
|
self.cdc_acm._update_output(idx, iface_idx, i_desc_obj)
|
||||||
|
|
||||||
# add cdc_union key if it doesn't exist and there are entries for
|
|
||||||
# this interface_descriptor
|
|
||||||
if self.cdc_union._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.cdc_union._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
self.cdc_union._update_output(idx, iface_idx, i_desc_obj)
|
self.cdc_union._update_output(idx, iface_idx, i_desc_obj)
|
||||||
|
|
||||||
# add hid_device_descriptor key if it doesn't exist and there are
|
|
||||||
# entries for this interface_descriptor
|
|
||||||
if self.hid_device_descriptor._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.hid_device_descriptor._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
self.hid_device_descriptor._update_output(idx, iface_idx, i_desc_obj)
|
self.hid_device_descriptor._update_output(idx, iface_idx, i_desc_obj)
|
||||||
|
|
||||||
@ -866,24 +857,18 @@ class _LsUsb():
|
|||||||
# i_desc_obj['hid_device_descriptor']['report_descriptors'].update(rd)
|
# i_desc_obj['hid_device_descriptor']['report_descriptors'].update(rd)
|
||||||
# del i_desc_obj['hid_device_descriptor']['report_descriptors'][keyname]['_state']
|
# del i_desc_obj['hid_device_descriptor']['report_descriptors'][keyname]['_state']
|
||||||
|
|
||||||
# add videocontrol_interface_descriptors key if it doesn't exist
|
|
||||||
# and there are entries for this interface_descriptor
|
|
||||||
if self.videocontrol_interface_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.videocontrol_interface_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
i_desc_obj['videocontrol_interface_descriptors'] = []
|
i_desc_obj['videocontrol_interface_descriptors'] = []
|
||||||
i_desc_obj['videocontrol_interface_descriptors'].extend(
|
i_desc_obj['videocontrol_interface_descriptors'].extend(
|
||||||
self.videocontrol_interface_descriptors._get_objects_list(idx, iface_idx)
|
self.videocontrol_interface_descriptors._get_objects_list(idx, iface_idx)
|
||||||
)
|
)
|
||||||
|
|
||||||
# add videostreaming_interface_descriptors key if it doesn't exist
|
|
||||||
# and there are entries for this interface_descriptor
|
|
||||||
if self.videostreaming_interface_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.videostreaming_interface_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
i_desc_obj['videostreaming_interface_descriptors'] = []
|
i_desc_obj['videostreaming_interface_descriptors'] = []
|
||||||
i_desc_obj['videostreaming_interface_descriptors'].extend(
|
i_desc_obj['videostreaming_interface_descriptors'].extend(
|
||||||
self.videostreaming_interface_descriptors._get_objects_list(idx, iface_idx)
|
self.videostreaming_interface_descriptors._get_objects_list(idx, iface_idx)
|
||||||
)
|
)
|
||||||
|
|
||||||
# add endpoint_descriptors key if it doesn't exist and there are
|
|
||||||
# entries for this interface_descriptor
|
|
||||||
if self.endpoint_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
if self.endpoint_descriptors._entries_for_this_bus_and_interface_idx_exist(idx, iface_idx):
|
||||||
i_desc_obj['endpoint_descriptors'] = []
|
i_desc_obj['endpoint_descriptors'] = []
|
||||||
i_desc_obj['endpoint_descriptors'].extend(
|
i_desc_obj['endpoint_descriptors'].extend(
|
||||||
@ -893,8 +878,7 @@ class _LsUsb():
|
|||||||
# add the object to the list of interface descriptors
|
# add the object to the list of interface descriptors
|
||||||
self.output_line['device_descriptor']['configuration_descriptor']['interface_descriptors'].append(i_desc_obj)
|
self.output_line['device_descriptor']['configuration_descriptor']['interface_descriptors'].append(i_desc_obj)
|
||||||
|
|
||||||
# add hub_descriptor key if it doesn't exist and there are
|
# add final root-level keys
|
||||||
# entries for this interface_descriptor
|
|
||||||
if self.hub_descriptor._entries_for_this_bus_exist(idx):
|
if self.hub_descriptor._entries_for_this_bus_exist(idx):
|
||||||
self.hub_descriptor._update_output(idx, self.output_line)
|
self.hub_descriptor._update_output(idx, self.output_line)
|
||||||
|
|
||||||
|
@ -7,25 +7,48 @@ Usage (cli):
|
|||||||
Usage (module):
|
Usage (module):
|
||||||
|
|
||||||
import jc
|
import jc
|
||||||
result = jc.parse('toml', toml_file)
|
result = jc.parse('toml', toml_file_output)
|
||||||
|
|
||||||
Schema:
|
Schema:
|
||||||
|
|
||||||
[
|
TOML Document converted to a Dictionary.
|
||||||
{
|
See https://toml.io/en/ for details.
|
||||||
"toml": string,
|
|
||||||
"bar": boolean,
|
{
|
||||||
"baz": integer
|
"key1": string/int/float/boolean/null/array/object,
|
||||||
}
|
"key2": string/int/float/boolean/null/array/object
|
||||||
]
|
}
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ toml | jc --toml -p
|
$ cat file.toml
|
||||||
[]
|
title = "TOML Example"
|
||||||
|
|
||||||
$ toml | jc --toml -p -r
|
[owner]
|
||||||
[]
|
name = "Tom Preston-Werner"
|
||||||
|
dob = 1979-05-27T07:32:00-08:00
|
||||||
|
|
||||||
|
[database]
|
||||||
|
enabled = true
|
||||||
|
ports = [ 8000, 8001, 8002 ]
|
||||||
|
|
||||||
|
$ cat file.toml | jc --toml -p
|
||||||
|
{
|
||||||
|
"title": "TOML Example",
|
||||||
|
"owner": {
|
||||||
|
"name": "Tom Preston-Werner",
|
||||||
|
"dob": 296667120,
|
||||||
|
"dob_iso": "1979-05-27T07:32:00-08:00"
|
||||||
|
},
|
||||||
|
"database": {
|
||||||
|
"enabled": true,
|
||||||
|
"ports": [
|
||||||
|
8000,
|
||||||
|
8001,
|
||||||
|
8002
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from jc.jc_types import JSONDictType
|
from jc.jc_types import JSONDictType
|
||||||
|
@ -13,8 +13,8 @@ Usage (module):
|
|||||||
|
|
||||||
Schema:
|
Schema:
|
||||||
|
|
||||||
YAML Document converted to a Dictionary
|
YAML Document converted to a Dictionary.
|
||||||
See https://pypi.org/project/ruamel.yaml for details
|
See https://pypi.org/project/ruamel.yaml for details.
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ Schema:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ cat istio-mtls-permissive.yaml
|
$ cat file.yaml
|
||||||
apiVersion: "authentication.istio.io/v1alpha1"
|
apiVersion: "authentication.istio.io/v1alpha1"
|
||||||
kind: "Policy"
|
kind: "Policy"
|
||||||
metadata:
|
metadata:
|
||||||
@ -46,7 +46,7 @@ Examples:
|
|||||||
tls:
|
tls:
|
||||||
mode: ISTIO_MUTUAL
|
mode: ISTIO_MUTUAL
|
||||||
|
|
||||||
$ cat istio-mtls-permissive.yaml | jc --yaml -p
|
$ cat file.yaml | jc --yaml -p
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"apiVersion": "authentication.istio.io/v1alpha1",
|
"apiVersion": "authentication.istio.io/v1alpha1",
|
||||||
|
@ -77,7 +77,7 @@ import jc.parsers.universal
|
|||||||
|
|
||||||
class info():
|
class info():
|
||||||
"""Provides parser metadata (version, author, etc.)"""
|
"""Provides parser metadata (version, author, etc.)"""
|
||||||
version = '1.1'
|
version = '1.2'
|
||||||
description = '`zipinfo` command parser'
|
description = '`zipinfo` command parser'
|
||||||
author = 'Matt J'
|
author = 'Matt J'
|
||||||
author_email = 'https://github.com/listuser'
|
author_email = 'https://github.com/listuser'
|
||||||
@ -170,7 +170,8 @@ def parse(data, raw=False, quiet=False):
|
|||||||
# 1st line
|
# 1st line
|
||||||
# Archive: log4j-core-2.16.0.jar
|
# Archive: log4j-core-2.16.0.jar
|
||||||
line = archive_item.pop(0)
|
line = archive_item.pop(0)
|
||||||
_, archive = line.split()
|
# remove prefix but don't split on spaces for files/paths with spaces
|
||||||
|
archive = line.replace('Archive: ', '', 1)
|
||||||
|
|
||||||
# 2nd line
|
# 2nd line
|
||||||
# Zip file size: 1789565 bytes, number of entries: 1218
|
# Zip file size: 1789565 bytes, number of entries: 1218
|
||||||
|
2
man/jc.1
2
man/jc.1
@ -1,4 +1,4 @@
|
|||||||
.TH jc 1 2023-01-05 1.22.5 "JSON Convert"
|
.TH jc 1 2023-01-06 1.22.5 "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
|
||||||
|
1
tests/fixtures/generic/toml-example.json
vendored
Normal file
1
tests/fixtures/generic/toml-example.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"title":"TOML Example","owner":{"name":"Lance Uppercut","dob":296667120,"dob_iso":"1979-05-27T07:32:00-08:00"},"database":{"server":"192.168.1.1","ports":[8001,8001,8002],"connection_max":5000,"enabled":true},"servers":{"alpha":{"ip":"10.0.0.1","dc":"eqdc10"},"beta":{"ip":"10.0.0.2","dc":"eqdc10"}},"clients":{"data":[["gamma","delta"],[1,2]],"hosts":["alpha","omega"]}}
|
27
tests/fixtures/generic/toml-example2.json
vendored
Normal file
27
tests/fixtures/generic/toml-example2.json
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"fruit": [
|
||||||
|
{
|
||||||
|
"name": "apple",
|
||||||
|
"physical": {
|
||||||
|
"color": "red",
|
||||||
|
"shape": "round"
|
||||||
|
},
|
||||||
|
"variety": [
|
||||||
|
{
|
||||||
|
"name": "red delicious"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "granny smith"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "banana",
|
||||||
|
"variety": [
|
||||||
|
{
|
||||||
|
"name": "plantain"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
18
tests/fixtures/generic/toml-example2.toml
vendored
Normal file
18
tests/fixtures/generic/toml-example2.toml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[[fruit]]
|
||||||
|
name = "apple"
|
||||||
|
|
||||||
|
[fruit.physical]
|
||||||
|
color = "red"
|
||||||
|
shape = "round"
|
||||||
|
|
||||||
|
[[fruit.variety]]
|
||||||
|
name = "red delicious"
|
||||||
|
|
||||||
|
[[fruit.variety]]
|
||||||
|
name = "granny smith"
|
||||||
|
|
||||||
|
[[fruit]]
|
||||||
|
name = "banana"
|
||||||
|
|
||||||
|
[[fruit.variety]]
|
||||||
|
name = "plantain"
|
1
tests/fixtures/rhel-8/zipinfo-space-in-name.json
vendored
Normal file
1
tests/fixtures/rhel-8/zipinfo-space-in-name.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1221
tests/fixtures/rhel-8/zipinfo-space-in-name.out
vendored
Normal file
1221
tests/fixtures/rhel-8/zipinfo-space-in-name.out
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -76,14 +76,19 @@ key: value1
|
|||||||
another_key = foo
|
another_key = foo
|
||||||
[section2]
|
[section2]
|
||||||
key3: bar
|
key3: bar
|
||||||
|
key4 =
|
||||||
|
[section 3]
|
||||||
|
key5 = "quoted"
|
||||||
'''
|
'''
|
||||||
expected = {
|
expected = {
|
||||||
'_top_level_section_': {
|
'key': 'value1',
|
||||||
'key': 'value1',
|
'another_key': 'foo',
|
||||||
'another_key': 'foo'
|
|
||||||
},
|
|
||||||
'section2': {
|
'section2': {
|
||||||
'key3': 'bar'
|
'key3': 'bar',
|
||||||
|
'key4': ''
|
||||||
|
},
|
||||||
|
'section 3': {
|
||||||
|
'key5': 'quoted'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.assertEqual(jc.parsers.ini.parse(data, quiet=True), expected)
|
self.assertEqual(jc.parsers.ini.parse(data, quiet=True), expected)
|
||||||
|
59
tests/test_toml.py
Normal file
59
tests/test_toml.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import json
|
||||||
|
from typing import Dict
|
||||||
|
from jc.parsers.toml import parse
|
||||||
|
|
||||||
|
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class MyTests(unittest.TestCase):
|
||||||
|
f_in: Dict = {}
|
||||||
|
f_json: Dict = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
fixtures = {
|
||||||
|
'toml1': (
|
||||||
|
'fixtures/generic/toml-example.toml',
|
||||||
|
'fixtures/generic/toml-example.json'),
|
||||||
|
'toml2': (
|
||||||
|
'fixtures/generic/toml-example2.toml',
|
||||||
|
'fixtures/generic/toml-example2.json')
|
||||||
|
}
|
||||||
|
|
||||||
|
for file, filepaths in fixtures.items():
|
||||||
|
with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
|
||||||
|
open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
|
||||||
|
cls.f_in[file] = a.read()
|
||||||
|
cls.f_json[file] = json.loads(b.read())
|
||||||
|
|
||||||
|
|
||||||
|
def test_toml_nodata(self):
|
||||||
|
"""
|
||||||
|
Test 'toml' with no data
|
||||||
|
"""
|
||||||
|
self.assertEqual(parse('', quiet=True), {})
|
||||||
|
|
||||||
|
|
||||||
|
def test_toml_example1(self):
|
||||||
|
"""
|
||||||
|
Test 'toml' with first example file
|
||||||
|
"""
|
||||||
|
self.assertEqual(
|
||||||
|
parse(self.f_in['toml1'], quiet=True),
|
||||||
|
self.f_json['toml1']
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_toml_example2(self):
|
||||||
|
"""
|
||||||
|
Test 'toml' with second example file
|
||||||
|
"""
|
||||||
|
self.assertEqual(
|
||||||
|
parse(self.f_in['toml2'], quiet=True),
|
||||||
|
self.f_json['toml2']
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -15,6 +15,9 @@ class MyTests(unittest.TestCase):
|
|||||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/zipinfo-multi.out'), 'r', encoding='utf-8') as f:
|
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/zipinfo-multi.out'), 'r', encoding='utf-8') as f:
|
||||||
osx_10_14_6_zipinfo_multi = f.read()
|
osx_10_14_6_zipinfo_multi = f.read()
|
||||||
|
|
||||||
|
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/rhel-8/zipinfo-space-in-name.out'), 'r', encoding='utf-8') as f:
|
||||||
|
rhel_8_zipinfo_space_in_name = f.read()
|
||||||
|
|
||||||
# output
|
# output
|
||||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/rhel-8/zipinfo.json'), 'r', encoding='utf-8') as f:
|
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/rhel-8/zipinfo.json'), 'r', encoding='utf-8') as f:
|
||||||
rhel_8_zipinfo_json = json.loads(f.read())
|
rhel_8_zipinfo_json = json.loads(f.read())
|
||||||
@ -22,6 +25,9 @@ class MyTests(unittest.TestCase):
|
|||||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/zipinfo-multi.json'), 'r', encoding='utf-8') as f:
|
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/zipinfo-multi.json'), 'r', encoding='utf-8') as f:
|
||||||
osx_10_14_6_zipinfo_multi_json = json.loads(f.read())
|
osx_10_14_6_zipinfo_multi_json = json.loads(f.read())
|
||||||
|
|
||||||
|
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/rhel-8/zipinfo-space-in-name.json'), 'r', encoding='utf-8') as f:
|
||||||
|
rhel_8_zipinfo_space_in_name_json = json.loads(f.read())
|
||||||
|
|
||||||
|
|
||||||
def test_zipinfo_nodata(self):
|
def test_zipinfo_nodata(self):
|
||||||
"""
|
"""
|
||||||
@ -41,6 +47,12 @@ class MyTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
self.assertEqual(jc.parsers.zipinfo.parse(self.osx_10_14_6_zipinfo_multi, quiet=True), self.osx_10_14_6_zipinfo_multi_json)
|
self.assertEqual(jc.parsers.zipinfo.parse(self.osx_10_14_6_zipinfo_multi, quiet=True), self.osx_10_14_6_zipinfo_multi_json)
|
||||||
|
|
||||||
|
def test_zipinfo_rhel_8_space_in_name(self):
|
||||||
|
"""
|
||||||
|
Test 'zipinfo' on Red Hat 8 with spaces in the file path
|
||||||
|
"""
|
||||||
|
self.assertEqual(jc.parsers.zipinfo.parse(self.rhel_8_zipinfo_space_in_name, quiet=True), self.rhel_8_zipinfo_space_in_name_json)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user