1
0
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:
Kelly Brazil
2022-10-07 16:36:46 -07:00
parent 81aa09a2e2
commit 4f294aa0ef
3 changed files with 35783 additions and 0 deletions

View File

@ -77,6 +77,7 @@ parsers = [
'nmcli', 'nmcli',
'ntpq', 'ntpq',
'passwd', 'passwd',
'pci-ids',
'pidstat', 'pidstat',
'pidstat-s', 'pidstat-s',
'ping', 'ping',

193
jc/parsers/pci_ids.py Normal file
View 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

File diff suppressed because it is too large Load Diff