mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-06-17 00:07:37 +02:00
add pci_ids parser
This commit is contained in:
@ -77,6 +77,7 @@ parsers = [
|
||||
'nmcli',
|
||||
'ntpq',
|
||||
'passwd',
|
||||
'pci-ids',
|
||||
'pidstat',
|
||||
'pidstat-s',
|
||||
'ping',
|
||||
|
193
jc/parsers/pci_ids.py
Normal file
193
jc/parsers/pci_ids.py
Normal file
@ -0,0 +1,193 @@
|
||||
"""jc - JSON Convert `pci.ids` file parser
|
||||
|
||||
This parser converts the pci.ids database file.
|
||||
|
||||
https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat pci.ids | jc --pci-ids
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('pci_ids', pci_ids_file_output)
|
||||
|
||||
Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"pci-id": string,
|
||||
"bar": boolean,
|
||||
"baz": integer
|
||||
}
|
||||
]
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat pci.ids | jc --pci-id -p
|
||||
[]
|
||||
|
||||
$ cat pci.ids | jc --pci-id -p -r
|
||||
[]
|
||||
"""
|
||||
import re
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`pci.ids` file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (List of Dictionaries) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured to conform to the schema.
|
||||
"""
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> Dict:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
raw_output: Dict = {}
|
||||
vdc_obj: Dict = {}
|
||||
vendor_id: str = ''
|
||||
device_id: str = ''
|
||||
|
||||
class_obj: Dict = {}
|
||||
class_id: str = ''
|
||||
subclass_id: str = ''
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
vdc_header_p = re.compile(r'^(?P<vendor_id>[0-9a-f]{4})\s+(?P<vendor_name>.+)')
|
||||
vdc_device_p = re.compile(r'^\t(?P<device_id>[0-9a-f]{4})\s+(?P<device_name>.+)')
|
||||
vdc_subvendor_p = re.compile(r'^\t\t(?P<subvendor>[0-9a-f]{4})\s+(?P<subdevice>[0-9a-f]{4})\s+(?P<subsystem_name>.+)')
|
||||
|
||||
class_header_p = re.compile(r'^C\s+(?P<class_id>[0-9a-f]{2})\s+(?P<class_name>.+)')
|
||||
class_sub_p = re.compile(r'^\t(?P<subclass_id>[0-9a-f]{2})\s+(?P<subclass_name>.+)')
|
||||
class_progif_p = re.compile(r'^\t\t(?P<prog_if_id>[0-9a-f]{2})\s+(?P<prog_if_name>.+)')
|
||||
|
||||
for line in filter(None, data.splitlines()):
|
||||
|
||||
vdc_header = vdc_header_p.match(line)
|
||||
vdc_device = vdc_device_p.match(line)
|
||||
vdc_subvendor = vdc_subvendor_p.match(line)
|
||||
|
||||
class_header = class_header_p.match(line)
|
||||
class_sub = class_sub_p.match(line)
|
||||
class_progif = class_progif_p.match(line)
|
||||
|
||||
# Vendors, devices and subsystems
|
||||
# Syntax:
|
||||
# vendor vendor_name
|
||||
# device device_name <-- single tab
|
||||
# subvendor subdevice subsystem_name <-- two tabs
|
||||
# Example:
|
||||
# 001c PEAK-System Technik GmbH
|
||||
# 0001 PCAN-PCI CAN-Bus controller
|
||||
# 001c 0004 2 Channel CAN Bus SJC1000
|
||||
if vdc_header:
|
||||
if vdc_obj:
|
||||
if 'vendors' not in raw_output:
|
||||
raw_output['vendors'] = {}
|
||||
raw_output['vendors'][vendor_id] = vdc_obj[vendor_id]
|
||||
vdc_obj = {}
|
||||
|
||||
vendor_id = vdc_header.groupdict()['vendor_id']
|
||||
vdc_obj[vendor_id] = {}
|
||||
vdc_obj[vendor_id]['vendor_name'] = vdc_header.groupdict()['vendor_name']
|
||||
continue
|
||||
|
||||
if vdc_device:
|
||||
device_id = vdc_device.groupdict()['device_id']
|
||||
vdc_obj[vendor_id][device_id] = {}
|
||||
vdc_obj[vendor_id][device_id]['device_name'] = vdc_device.groupdict()['device_name']
|
||||
continue
|
||||
|
||||
if vdc_subvendor:
|
||||
subvendor = vdc_subvendor.groupdict()['subvendor']
|
||||
subdevice = vdc_subvendor.groupdict()['subdevice']
|
||||
vdc_obj[vendor_id][device_id][subvendor] = {}
|
||||
vdc_obj[vendor_id][device_id][subvendor][subdevice] = {}
|
||||
vdc_obj[vendor_id][device_id][subvendor][subdevice]['subsystem_name'] = vdc_subvendor.groupdict()['subsystem_name']
|
||||
continue
|
||||
|
||||
# List of known device classes, subclasses and programming interfaces
|
||||
# Syntax:
|
||||
# C class class_name
|
||||
# subclass subclass_name <-- single tab
|
||||
# prog-if prog-if_name <-- two tabs
|
||||
# Example:
|
||||
# C 01 Mass storage controller
|
||||
# 01 IDE interface
|
||||
# 00 ISA Compatibility mode-only controller
|
||||
if class_header:
|
||||
if class_obj:
|
||||
if 'classes' not in raw_output:
|
||||
raw_output['classes'] = {}
|
||||
raw_output['classes'][class_id] = class_obj[class_id]
|
||||
class_obj = {}
|
||||
|
||||
class_id = class_header.groupdict()['class_id']
|
||||
class_obj[class_id] = {}
|
||||
class_obj[class_id]['class_name'] = class_header.groupdict()['class_name']
|
||||
continue
|
||||
|
||||
if class_sub:
|
||||
subclass_id = class_sub.groupdict()['subclass_id']
|
||||
class_obj[class_id][subclass_id] = {}
|
||||
class_obj[class_id][subclass_id]['subclass_name'] = class_sub.groupdict()['subclass_name']
|
||||
continue
|
||||
|
||||
if class_progif:
|
||||
prog_if_id = class_progif.groupdict()['prog_if_id']
|
||||
class_obj[class_id][subclass_id][prog_if_id] = class_progif.groupdict()['prog_if_name']
|
||||
continue
|
||||
|
||||
if vdc_obj:
|
||||
if 'vendors' not in raw_output:
|
||||
raw_output['vendors'] = {}
|
||||
raw_output['vendors'][vendor_id] = vdc_obj[vendor_id]
|
||||
|
||||
if class_obj:
|
||||
if 'classes' not in raw_output:
|
||||
raw_output['classes'] = {}
|
||||
raw_output['classes'][class_id] = class_obj[class_id]
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
35589
tests/fixtures/generic/pci.ids
vendored
Normal file
35589
tests/fixtures/generic/pci.ids
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user