diff --git a/jc/parsers/acpi.py b/jc/parsers/acpi.py index 30cf5b1d..0069fcae 100644 --- a/jc/parsers/acpi.py +++ b/jc/parsers/acpi.py @@ -236,8 +236,6 @@ class info(): description = '`acpi` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['acpi'] @@ -257,7 +255,8 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ - int_list = ['id', 'charge_percent', 'design_capacity_mah', 'last_full_capacity', 'last_full_capacity_percent'] + int_list = ['id', 'charge_percent', 'design_capacity_mah', 'last_full_capacity', + 'last_full_capacity_percent'] float_list = ['temperature'] for entry in proc_data: diff --git a/jc/parsers/airport.py b/jc/parsers/airport.py index 6d022850..641b7450 100644 --- a/jc/parsers/airport.py +++ b/jc/parsers/airport.py @@ -89,9 +89,6 @@ class info(): description = '`airport -I` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['darwin'] magic_commands = ['airport -I'] @@ -144,7 +141,9 @@ def parse(data, raw=False, quiet=False): for line in filter(None, data.splitlines()): linedata = line.split(':', maxsplit=1) - raw_output[linedata[0].strip().lower().replace(' ', '_').replace('.', '_')] = linedata[1].strip() + key = linedata[0].strip().lower().replace(' ', '_').replace('.', '_') + value = linedata[1].strip() + raw_output[key] = value if raw: return raw_output diff --git a/jc/parsers/airport_s.py b/jc/parsers/airport_s.py index 9fd18aa3..5f6dc4fd 100644 --- a/jc/parsers/airport_s.py +++ b/jc/parsers/airport_s.py @@ -118,9 +118,6 @@ class info(): description = '`airport -s` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['darwin'] magic_commands = ['airport -s'] diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 180c8e36..f1a35ea9 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -127,8 +127,6 @@ class info(): description = '`arp` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'aix', 'freebsd', 'darwin'] magic_commands = ['arp'] diff --git a/jc/parsers/blkid.py b/jc/parsers/blkid.py index b1d920c1..f1f03068 100644 --- a/jc/parsers/blkid.py +++ b/jc/parsers/blkid.py @@ -130,9 +130,6 @@ class info(): description = '`blkid` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['blkid'] @@ -156,9 +153,10 @@ def _process(proc_data): if 'devname' in entry: entry['device'] = entry.pop('devname') - int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size', 'id_part_entry_number', - 'id_part_entry_offset', 'id_part_entry_size', 'minimum_io_size', 'physical_sector_size', - 'logical_sector_size', 'id_iolimit_minimum_io_size', 'id_iolimit_physical_sector_size', + int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size', + 'id_part_entry_number', 'id_part_entry_offset', 'id_part_entry_size', + 'minimum_io_size', 'physical_sector_size', 'logical_sector_size', + 'id_iolimit_minimum_io_size', 'id_iolimit_physical_sector_size', 'id_iolimit_logical_sector_size'] for key in entry: if key in int_list: diff --git a/jc/parsers/cksum.py b/jc/parsers/cksum.py index 8083de92..4ebc74ca 100644 --- a/jc/parsers/cksum.py +++ b/jc/parsers/cksum.py @@ -63,8 +63,6 @@ class info(): description = '`cksum` and `sum` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['cksum', 'sum'] diff --git a/jc/parsers/crontab.py b/jc/parsers/crontab.py index d933e771..537bbf2a 100644 --- a/jc/parsers/crontab.py +++ b/jc/parsers/crontab.py @@ -1,4 +1,5 @@ -"""jc - JSON CLI output utility `crontab -l` command output and crontab file parser +"""jc - JSON CLI output utility `crontab -l` command output and crontab +file parser Supports `crontab -l` command output and crontab files. @@ -182,9 +183,6 @@ class info(): description = '`crontab` command and file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] magic_commands = ['crontab'] diff --git a/jc/parsers/crontab_u.py b/jc/parsers/crontab_u.py index eeadb6cb..b41269bf 100644 --- a/jc/parsers/crontab_u.py +++ b/jc/parsers/crontab_u.py @@ -1,6 +1,8 @@ -"""jc - JSON CLI output utility `crontab -l` command output and crontab file parser +"""jc - JSON CLI output utility `crontab -l` command output and crontab +file parser -This version of the `crontab -l` parser supports output that contains user information for processes. +This version of the `crontab -l` parser supports output that contains user +information for processes. Usage (cli): @@ -57,7 +59,7 @@ Examples: "variables": [ { "name": "PATH", - "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" + "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sb..." }, { "name": "SHELL", @@ -82,7 +84,7 @@ Examples: "*" ], "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." }, { "minute": [ @@ -101,7 +103,7 @@ Examples: "7" ], "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." }, { "minute": [ @@ -120,7 +122,7 @@ Examples: "*" ], "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." } ] } @@ -130,7 +132,7 @@ Examples: "variables": [ { "name": "PATH", - "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" + "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/..." }, { "name": "SHELL", @@ -145,7 +147,7 @@ Examples: "month": "*", "day_of_week": "*", "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." }, { "minute": "47", @@ -154,7 +156,7 @@ Examples: "month": "*", "day_of_week": "7", "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." }, { "minute": "52", @@ -163,7 +165,7 @@ Examples: "month": "*", "day_of_week": "*", "user": "root", - "command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )" + "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..." } ] } @@ -178,9 +180,6 @@ class info(): description = '`crontab` file parser with user support' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] diff --git a/jc/parsers/csv.py b/jc/parsers/csv.py index 7a32489a..154d6b45 100644 --- a/jc/parsers/csv.py +++ b/jc/parsers/csv.py @@ -1,6 +1,8 @@ """jc - JSON CLI output utility `csv` file parser -The `csv` parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row. +The `csv` parser will attempt to automatically detect the delimiter +character. If the delimiter cannot be detected it will default to comma. The +first row of the file must be a header row. Usage (cli): @@ -18,7 +20,8 @@ Usage (module): Schema: - csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html + csv file converted to a Dictionary: + https://docs.python.org/3/library/csv.html [ { @@ -30,7 +33,7 @@ Schema: Examples: $ cat homes.csv - "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes" + "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres"... 142, 160, 28, 10, 5, 3, 60, 0.28, 3167 175, 180, 18, 8, 4, 1, 12, 0.43, 4033 129, 132, 13, 6, 3, 1, 41, 0.33, 1471 @@ -85,8 +88,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using the python standard csv library' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] @@ -103,7 +104,8 @@ def _process(proc_data): Returns: - List of Dictionaries. Each Dictionary represents a row in the csv file. + List of Dictionaries. Each Dictionary represents a row in the csv + file. """ # No further processing diff --git a/jc/parsers/csv_s.py b/jc/parsers/csv_s.py index 4e030cce..aeaea162 100644 --- a/jc/parsers/csv_s.py +++ b/jc/parsers/csv_s.py @@ -2,9 +2,12 @@ > This streaming parser outputs JSON Lines -The `csv` streaming parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row. +The `csv` streaming parser will attempt to automatically detect the +delimiter character. If the delimiter cannot be detected it will default +to comma. The first row of the file must be a header row. -Note: The first 100 rows are read into memory to enable delimiter detection, then the rest of the rows are loaded lazily. +Note: The first 100 rows are read into memory to enable delimiter detection, +then the rest of the rows are loaded lazily. Usage (cli): @@ -13,27 +16,33 @@ Usage (cli): Usage (module): import jc - result = jc.parse('csv_s', csv_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('csv_s', csv_output.splitlines()) for item in result: # do something or import jc.parsers.csv_s - result = jc.parsers.csv_s.parse(csv_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.csv_s.parse(csv_output.splitlines()) for item in result: # do something Schema: - csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html + csv file converted to a Dictionary: + https://docs.python.org/3/library/csv.html { "column_name1": string, "column_name2": string, - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + + # below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error + "success": boolean, # false if error parsing "error": string, # exists if "success" is false "line": string # exists if "success" is false } @@ -42,16 +51,16 @@ Schema: Examples: $ cat homes.csv - "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes" + "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres"... 142, 160, 28, 10, 5, 3, 60, 0.28, 3167 175, 180, 18, 8, 4, 1, 12, 0.43, 4033 129, 132, 13, 6, 3, 1, 41, 0.33, 1471 ... $ cat homes.csv | jc --csv-s - {"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5","Baths":"3","Age":"60","Acres":"0.28","Taxes":"3167"} - {"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4","Baths":"1","Age":"12","Acres":"0.43","Taxes":"4033"} - {"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3","Baths":"1","Age":"41","Acres":"0.33","Taxes":"1471"} + {"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5"...} + {"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4"...} + {"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3"...} ... """ import itertools @@ -85,7 +94,8 @@ def _process(proc_data): Returns: - List of Dictionaries. Each Dictionary represents a row in the csv file. + List of Dictionaries. Each Dictionary represents a row in the csv + file. """ # No further processing return proc_data @@ -97,7 +107,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/date.py b/jc/parsers/date.py index c022d98f..d28efc2a 100644 --- a/jc/parsers/date.py +++ b/jc/parsers/date.py @@ -1,8 +1,10 @@ """jc - JSON CLI output utility `date` command output parser -The `epoch` calculated timestamp field is naive. (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the timezone field is UTC. Usage (cli): @@ -37,15 +39,19 @@ Schema: "second": integer, "period": string, "timezone": string, - "utc_offset": string, # null if timezone field is not UTC + "utc_offset": string, # null if timezone field is not UTC "day_of_year": integer, "week_of_year": integer, "iso": string, - "epoch": integer, # naive timestamp - "epoch_utc": integer, # timezone-aware timestamp. Only available if timezone field is UTC - "timezone_aware": boolean # if true, all fields are correctly based on UTC + "epoch": integer, # [0] + "epoch_utc": integer, # [1] + "timezone_aware": boolean # [2] } + [0] naive timestamp + [1] timezone-aware timestamp. Only available if timezone field is UTC + [2] if true, all fields are correctly based on UTC + Examples: $ date | jc --date -p @@ -81,8 +87,6 @@ class info(): description = '`date` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['date'] @@ -129,28 +133,33 @@ def parse(data, raw=False, quiet=False): # find the timezone no matter where it is in the string # from https://www.timeanddate.com/time/zones/ - tz_abbr = ['A', 'ACDT', 'ACST', 'ACT', 'ACWST', 'ADT', 'AEDT', 'AEST', 'AET', 'AFT', 'AKDT', 'AKST', 'ALMT', - 'AMST', 'AMT', 'ANAST', 'ANAT', 'AQTT', 'ART', 'AST', 'AT', 'AWDT', 'AWST', 'AZOST', 'AZOT', - 'AZST', 'AZT', 'AoE', 'B', 'BNT', 'BOT', 'BRST', 'BRT', 'BST', 'BTT', 'C', 'CAST', 'CAT', 'CCT', - 'CDT', 'CEST', 'CET', 'CHADT', 'CHAST', 'CHOST', 'CHOT', 'CHUT', 'CIDST', 'CIST', 'CKT', 'CLST', - 'CLT', 'COT', 'CST', 'CT', 'CVT', 'CXT', 'ChST', 'D', 'DAVT', 'DDUT', 'E', 'EASST', 'EAST', - 'EAT', 'ECT', 'EDT', 'EEST', 'EET', 'EGST', 'EGT', 'EST', 'ET', 'F', 'FET', 'FJST', 'FJT', 'FKST', - 'FKT', 'FNT', 'G', 'GALT', 'GAMT', 'GET', 'GFT', 'GILT', 'GMT', 'GST', 'GYT', 'H', 'HDT', 'HKT', - 'HOVST', 'HOVT', 'HST', 'I', 'ICT', 'IDT', 'IOT', 'IRDT', 'IRKST', 'IRKT', 'IRST', 'IST', 'JST', - 'K', 'KGT', 'KOST', 'KRAST', 'KRAT', 'KST', 'KUYT', 'L', 'LHDT', 'LHST', 'LINT', 'M', 'MAGST', - 'MAGT', 'MART', 'MAWT', 'MDT', 'MHT', 'MMT', 'MSD', 'MSK', 'MST', 'MT', 'MUT', 'MVT', 'MYT', 'N', - 'NCT', 'NDT', 'NFDT', 'NFT', 'NOVST', 'NOVT', 'NPT', 'NRT', 'NST', 'NUT', 'NZDT', 'NZST', 'O', - 'OMSST', 'OMST', 'ORAT', 'P', 'PDT', 'PET', 'PETST', 'PETT', 'PGT', 'PHOT', 'PHT', 'PKT', 'PMDT', - 'PMST', 'PONT', 'PST', 'PT', 'PWT', 'PYST', 'PYT', 'Q', 'QYZT', 'R', 'RET', 'ROTT', 'S', 'SAKT', - 'SAMT', 'SAST', 'SBT', 'SCT', 'SGT', 'SRET', 'SRT', 'SST', 'SYOT', 'T', 'TAHT', 'TFT', 'TJT', 'TKT', - 'TLT', 'TMT', 'TOST', 'TOT', 'TRT', 'TVT', 'U', 'ULAST', 'ULAT', 'UYST', 'UYT', 'UZT', 'V', 'VET', - 'VLAST', 'VLAT', 'VOST', 'VUT', 'W', 'WAKT', 'WARST', 'WAST', 'WAT', 'WEST', 'WET', 'WFT', 'WGST', - 'WGT', 'WIB', 'WIT', 'WITA', 'WST', 'WT', 'X', 'Y', 'YAKST', 'YAKT', 'YAPT', 'YEKST', 'YEKT', 'Z', - 'UTC', 'UTC-1200', 'UTC-1100', 'UTC-1000', 'UTC-0930', 'UTC-0900', 'UTC-0800', 'UTC-0700', 'UTC-0600', - 'UTC-0500', 'UTC-0400', 'UTC-0300', 'UTC-0230', 'UTC-0200', 'UTC-0100', 'UTC+0000', 'UTC-0000', - 'UTC+0100', 'UTC+0200', 'UTC+0300', 'UTC+0400', 'UTC+0430', 'UTC+0500', 'UTC+0530', 'UTC+0545', - 'UTC+0600', 'UTC+0630', 'UTC+0700', 'UTC+0800', 'UTC+0845', 'UTC+0900', 'UTC+1000', 'UTC+1030', - 'UTC+1100', 'UTC+1200', 'UTC+1300', 'UTC+1345', 'UTC+1400'] + tz_abbr = [ + 'A', 'ACDT', 'ACST', 'ACT', 'ACWST', 'ADT', 'AEDT', 'AEST', 'AET', 'AFT', 'AKDT', + 'AKST', 'ALMT', 'AMST', 'AMT', 'ANAST', 'ANAT', 'AQTT', 'ART', 'AST', 'AT', 'AWDT', + 'AWST', 'AZOST', 'AZOT', 'AZST', 'AZT', 'AoE', 'B', 'BNT', 'BOT', 'BRST', 'BRT', 'BST', + 'BTT', 'C', 'CAST', 'CAT', 'CCT', 'CDT', 'CEST', 'CET', 'CHADT', 'CHAST', 'CHOST', + 'CHOT', 'CHUT', 'CIDST', 'CIST', 'CKT', 'CLST', 'CLT', 'COT', 'CST', 'CT', 'CVT', 'CXT', + 'ChST', 'D', 'DAVT', 'DDUT', 'E', 'EASST', 'EAST', 'EAT', 'ECT', 'EDT', 'EEST', 'EET', + 'EGST', 'EGT', 'EST', 'ET', 'F', 'FET', 'FJST', 'FJT', 'FKST', 'FKT', 'FNT', 'G', + 'GALT', 'GAMT', 'GET', 'GFT', 'GILT', 'GMT', 'GST', 'GYT', 'H', 'HDT', 'HKT', 'HOVST', + 'HOVT', 'HST', 'I', 'ICT', 'IDT', 'IOT', 'IRDT', 'IRKST', 'IRKT', 'IRST', 'IST', 'JST', + 'K', 'KGT', 'KOST', 'KRAST', 'KRAT', 'KST', 'KUYT', 'L', 'LHDT', 'LHST', 'LINT', 'M', + 'MAGST', 'MAGT', 'MART', 'MAWT', 'MDT', 'MHT', 'MMT', 'MSD', 'MSK', 'MST', 'MT', 'MUT', + 'MVT', 'MYT', 'N', 'NCT', 'NDT', 'NFDT', 'NFT', 'NOVST', 'NOVT', 'NPT', 'NRT', 'NST', + 'NUT', 'NZDT', 'NZST', 'O', 'OMSST', 'OMST', 'ORAT', 'P', 'PDT', 'PET', 'PETST', 'PETT', + 'PGT', 'PHOT', 'PHT', 'PKT', 'PMDT', 'PMST', 'PONT', 'PST', 'PT', 'PWT', 'PYST', 'PYT', + 'Q', 'QYZT', 'R', 'RET', 'ROTT', 'S', 'SAKT', 'SAMT', 'SAST', 'SBT', 'SCT', 'SGT', + 'SRET', 'SRT', 'SST', 'SYOT', 'T', 'TAHT', 'TFT', 'TJT', 'TKT', 'TLT', 'TMT', 'TOST', + 'TOT', 'TRT', 'TVT', 'U', 'ULAST', 'ULAT', 'UYST', 'UYT', 'UZT', 'V', 'VET', 'VLAST', + 'VLAT', 'VOST', 'VUT', 'W', 'WAKT', 'WARST', 'WAST', 'WAT', 'WEST', 'WET', 'WFT', + 'WGST', 'WGT', 'WIB', 'WIT', 'WITA', 'WST', 'WT', 'X', 'Y', 'YAKST', 'YAKT', 'YAPT', + 'YEKST', 'YEKT', 'Z', 'UTC', 'UTC-1200', 'UTC-1100', 'UTC-1000', 'UTC-0930', 'UTC-0900', + 'UTC-0800', 'UTC-0700', 'UTC-0600', 'UTC-0500', 'UTC-0400', 'UTC-0300', 'UTC-0230', + 'UTC-0200', 'UTC-0100', 'UTC+0000', 'UTC-0000', 'UTC+0100', 'UTC+0200', 'UTC+0300', + 'UTC+0400', 'UTC+0430', 'UTC+0500', 'UTC+0530', 'UTC+0545', 'UTC+0600', 'UTC+0630', + 'UTC+0700', 'UTC+0800', 'UTC+0845', 'UTC+0900', 'UTC+1000', 'UTC+1030', 'UTC+1100', + 'UTC+1200', 'UTC+1300', 'UTC+1345', 'UTC+1400' + ] tz = None for term in data.replace('(', '').replace(')', '').split(): if term in tz_abbr: diff --git a/jc/parsers/df.py b/jc/parsers/df.py index ea69e35b..34a156db 100644 --- a/jc/parsers/df.py +++ b/jc/parsers/df.py @@ -108,8 +108,6 @@ class info(): description = '`df` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['df'] @@ -163,7 +161,8 @@ def _process(proc_data): entry['iused_percent'] = entry['iused_percent'].rstrip('%') # change used, available, use_percent, capacity_percent, ifree, iused, iused_percent to int - int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree', 'iused', 'iused_percent'] + int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree', + 'iused', 'iused_percent'] for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) @@ -172,7 +171,10 @@ def _process(proc_data): def _long_filesystem_hash(header, line): - """Returns truncated hash and value of the filesystem field if it is too long for the column""" + """ + Returns truncated hash and value of the filesystem field if it is too + long for the column. + """ filesystem_field = line.split()[0] # get length of filesystem column @@ -238,7 +240,8 @@ def parse(data, raw=False, quiet=False): # parse the data raw_output = jc.parsers.universal.sparse_table_parse(fix_data) - # replace hash values with real values to fix long filesystem data in some older versions of df + # replace hash values with real values to fix long filesystem data + # in some older versions of df for item in raw_output: if 'filesystem' in item: if item['filesystem'] in filesystem_map: diff --git a/jc/parsers/dig.py b/jc/parsers/dig.py index d1216f66..bfe61e1d 100644 --- a/jc/parsers/dig.py +++ b/jc/parsers/dig.py @@ -1,12 +1,15 @@ """jc - JSON CLI output utility `dig` command output parser Options supported: -- `+noall +answer` options are supported in cases where only the answer information is desired. +- `+noall +answer` options are supported in cases where only the answer + information is desired. - `+axfr` option is supported on its own -The `when_epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `when_epoch` calculated timestamp field is naive. (i.e. based on the +local time of the system the parser is run on) -The `when_epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `when_epoch_utc` calculated timestamp field is timezone-aware and is +only available if the timezone field is UTC. Usage (cli): @@ -95,13 +98,16 @@ Schema: "query_time": integer, # in msec "server": string, "when": string, - "when_epoch": integer, # naive timestamp if when field is parsable, else null - "when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null + "when_epoch": integer, # [0] + "when_epoch_utc": integer, # [1] "rcvd": integer "size": string } ] + [0] naive timestamp if when field is parsable, else null + [1] timezone aware timestamp availabe for UTC, else null + Examples: $ dig example.com | jc --dig -p @@ -325,8 +331,6 @@ class info(): description = '`dig` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin'] magic_commands = ['dig'] @@ -347,8 +351,8 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ for entry in proc_data: - int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', 'rcvd', - 'query_size', 'query_time'] + int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', + 'rcvd', 'query_size', 'query_time'] for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) @@ -360,10 +364,12 @@ def _process(proc_data): if 'opt_pseudosection' in entry: if 'edns' in entry['opt_pseudosection']: if 'version' in entry['opt_pseudosection']['edns']: - entry['opt_pseudosection']['edns']['version'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version']) + val = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version']) + entry['opt_pseudosection']['edns']['version'] = val if 'udp' in entry['opt_pseudosection']['edns']: - entry['opt_pseudosection']['edns']['udp'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp']) + val = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp']) + entry['opt_pseudosection']['edns']['udp'] = val if 'answer' in entry: for ans in entry['answer']: diff --git a/jc/parsers/dir.py b/jc/parsers/dir.py index 9d8954d4..625966f3 100644 --- a/jc/parsers/dir.py +++ b/jc/parsers/dir.py @@ -6,9 +6,11 @@ Options supported: - `/C, /-C` - `/S` -The "Magic" syntax is not supported since the `dir` command is a shell builtin. +The "Magic" syntax is not supported since the `dir` command is a shell +builtin. -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) Usage (cli): @@ -128,8 +130,6 @@ class info(): description = '`dir` command parser' author = 'Rasheed Elsaleh' author_email = 'rasheed@rebelliondefense.com' - - # compatible options: win32 compatible = ['win32'] diff --git a/jc/parsers/dmidecode.py b/jc/parsers/dmidecode.py index 3cd408fd..b9be6975 100644 --- a/jc/parsers/dmidecode.py +++ b/jc/parsers/dmidecode.py @@ -134,9 +134,6 @@ class info(): description = '`dmidecode` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['dmidecode'] diff --git a/jc/parsers/dpkg_l.py b/jc/parsers/dpkg_l.py index 72328fcb..9f6916d4 100644 --- a/jc/parsers/dpkg_l.py +++ b/jc/parsers/dpkg_l.py @@ -1,6 +1,7 @@ """jc - JSON CLI output utility `dpkg -l` command output parser -Set the `COLUMNS` environment variable to a large value to avoid field truncation. For example: +Set the `COLUMNS` environment variable to a large value to avoid field +truncation. For example: $ COLUMNS=500 dpkg -l | jc --dpkg-l @@ -74,7 +75,7 @@ Examples: "name": "acpid", "version": "1:2.0.28-1ubuntu1", "architecture": "amd64", - "description": "Advanced Configuration and Power Interface event daemon", + "description": "Advanced Configuration and Power Interface...", "desired": "remove", "status": "half installed" }, @@ -118,7 +119,7 @@ Examples: "name": "acpid", "version": "1:2.0.28-1ubuntu1", "architecture": "amd64", - "description": "Advanced Configuration and Power Interface event daemon" + "description": "Advanced Configuration and Power Interface..." }, { "codes": "pn", @@ -140,9 +141,6 @@ class info(): description = '`dpkg -l` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['dpkg -l'] diff --git a/jc/parsers/du.py b/jc/parsers/du.py index 984c9173..b27b01ce 100644 --- a/jc/parsers/du.py +++ b/jc/parsers/du.py @@ -37,23 +37,23 @@ Examples: }, { "size": 56, - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": 0, - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": 0, - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": 0, - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": 1008, - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, ... ] @@ -66,23 +66,23 @@ Examples: }, { "size": "56", - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": "0", - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": "0", - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": "0", - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, { "size": "1008", - "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu" + "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..." }, ... ] @@ -97,9 +97,6 @@ class info(): description = '`du` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] magic_commands = ['du'] diff --git a/jc/parsers/env.py b/jc/parsers/env.py index 18fa3d37..59d314dd 100644 --- a/jc/parsers/env.py +++ b/jc/parsers/env.py @@ -1,6 +1,9 @@ """jc - JSON CLI output utility `env` and `printenv` command output parser -This parser will output a list of dictionaries each containing `name` and `value` keys. If you would like a simple dictionary output, then use the `-r` command-line option or the `raw=True` argument in the `parse()` function. +This parser will output a list of dictionaries each containing `name` and +`value` keys. If you would like a simple dictionary output, then use the +`-r` command-line option or the `raw=True` argument in the `parse()` +function. Usage (cli): @@ -78,8 +81,6 @@ class info(): description = '`env` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] magic_commands = ['env', 'printenv'] diff --git a/jc/parsers/file.py b/jc/parsers/file.py index c745cbf7..12d986c2 100644 --- a/jc/parsers/file.py +++ b/jc/parsers/file.py @@ -53,11 +53,11 @@ Examples: }, { "filename": "cd_catalog.xml", - "type": "XML 1.0 document text, ASCII text, with CRLF line terminators" + "type": "XML 1.0 document text, ASCII text, with CRLF line ..." }, { "filename": "centosserial.sh", - "type": "Bourne-Again shell script text executable, UTF-8 Unicode text" + "type": "Bourne-Again shell script text executable, UTF-8 ..." }, ... ] @@ -72,8 +72,6 @@ class info(): description = '`file` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'aix', 'freebsd', 'darwin'] magic_commands = ['file'] diff --git a/jc/parsers/finger.py b/jc/parsers/finger.py index a8128a56..0284a140 100644 --- a/jc/parsers/finger.py +++ b/jc/parsers/finger.py @@ -101,9 +101,6 @@ class info(): description = '`finger` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'freebsd'] magic_commands = ['finger'] @@ -179,11 +176,12 @@ def parse(data, raw=False, quiet=False): raw_output = [] if jc.utils.has_data(data): - # Finger output is an abomination that is nearly unparsable. But there is a way: - # First find the location of the last character of 'Idle' in the table and cut - # all lines at that spot. Data before that spot can use the unviversal.sparse_table_parse function. - # All data after that spot can be run through regex to find the login datetime and possibly - # other fields. + # Finger output is an abomination that is nearly unparsable. But there + # is a way: + # First find the location of the last character of 'Idle' in the table + # and cut all lines at that spot. Data before that spot can use the + # unviversal.sparse_table_parse function. All data after that spot can + # be run through regex to find the login datetime and possibly other fields. data_lines = list(filter(None, data.splitlines())) sep_col = data_lines[0].find('Idle') + 4 diff --git a/jc/parsers/foo.py b/jc/parsers/foo.py index 9ae77501..36db9cd7 100644 --- a/jc/parsers/foo.py +++ b/jc/parsers/foo.py @@ -72,7 +72,8 @@ def _process(proc_data): # process the data here # rebuild output for added semantic information - # use helper functions in jc.utils for int, float, bool conversions and timestamps + # use helper functions in jc.utils for int, float, bool + # conversions and timestamps return proc_data diff --git a/jc/parsers/foo_s.py b/jc/parsers/foo_s.py index 32ab00b6..45e56d48 100644 --- a/jc/parsers/foo_s.py +++ b/jc/parsers/foo_s.py @@ -11,14 +11,16 @@ Usage (cli): Usage (module): import jc - result = jc.parse('foo_s', foo_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('foo_s', foo_command_output.splitlines()) for item in result: # do something or import jc.parsers.foo_s - result = jc.parsers.foo_s.parse(foo_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.foo_s.parse(foo_command_output.splitlines()) for item in result: # do something @@ -26,9 +28,12 @@ Schema: { "foo": string, - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error + "success": boolean, # false if error parsing "error": string, # exists if "success" is false "line": string # exists if "success" is false } @@ -76,11 +81,11 @@ def _process(proc_data): Dictionary. Structured data to conform to the schema. """ - # + # process the data here # rebuild output for added semantic information - # use helper functions in jc.utils for int, float, bool conversions and timestamps - # + # use helper functions in jc.utils for int, float, + # bool conversions and timestamps return proc_data @@ -91,7 +96,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/free.py b/jc/parsers/free.py index be6dc991..6e481128 100644 --- a/jc/parsers/free.py +++ b/jc/parsers/free.py @@ -82,8 +82,6 @@ class info(): description = '`free` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['free'] diff --git a/jc/parsers/fstab.py b/jc/parsers/fstab.py index 56bec679..c8174043 100644 --- a/jc/parsers/fstab.py +++ b/jc/parsers/fstab.py @@ -94,8 +94,6 @@ class info(): description = '`/etc/fstab` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'freebsd'] diff --git a/jc/parsers/group.py b/jc/parsers/group.py index 05e2629b..117dc42a 100644 --- a/jc/parsers/group.py +++ b/jc/parsers/group.py @@ -118,9 +118,6 @@ class info(): description = '`/etc/group` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] diff --git a/jc/parsers/gshadow.py b/jc/parsers/gshadow.py index b4a52d27..5d12a7f7 100644 --- a/jc/parsers/gshadow.py +++ b/jc/parsers/gshadow.py @@ -86,9 +86,6 @@ class info(): description = '`/etc/gshadow` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'aix', 'freebsd'] diff --git a/jc/parsers/hash.py b/jc/parsers/hash.py index 6c5bf970..023be044 100644 --- a/jc/parsers/hash.py +++ b/jc/parsers/hash.py @@ -47,8 +47,6 @@ class info(): description = '`hash` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] diff --git a/jc/parsers/hashsum.py b/jc/parsers/hashsum.py index aee08695..f27a6ea4 100644 --- a/jc/parsers/hashsum.py +++ b/jc/parsers/hashsum.py @@ -78,10 +78,9 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Parses MD5 and SHA hash program output' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] - magic_commands = ['md5sum', 'md5', 'shasum', 'sha1sum', 'sha224sum', 'sha256sum', 'sha384sum', 'sha512sum'] + magic_commands = ['md5sum', 'md5', 'shasum', 'sha1sum', 'sha224sum', + 'sha256sum', 'sha384sum', 'sha512sum'] __version__ = info.version diff --git a/jc/parsers/hciconfig.py b/jc/parsers/hciconfig.py index 3e55aeac..20153b65 100644 --- a/jc/parsers/hciconfig.py +++ b/jc/parsers/hciconfig.py @@ -326,9 +326,6 @@ class info(): description = '`hciconfig` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['hciconfig'] @@ -351,13 +348,17 @@ def _process(proc_data): for entry in proc_data: - int_list = ['acl_mtu', 'acl_mtu_packets', 'sco_mtu', 'sco_mtu_packets', 'rx_bytes', 'rx_acl', 'rx_sco', - 'rx_events', 'rx_errors', 'tx_bytes', 'tx_acl', 'tx_sco', 'tx_commands', 'tx_errors'] + int_list = ['acl_mtu', 'acl_mtu_packets', 'sco_mtu', 'sco_mtu_packets', + 'rx_bytes', 'rx_acl', 'rx_sco', 'rx_events', 'rx_errors', + 'tx_bytes', 'tx_acl', 'tx_sco', 'tx_commands', 'tx_errors'] for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) - if 'service_classes' in entry and len(entry['service_classes']) == 1 and 'Unspecified' in entry['service_classes']: + if ('service_classes' in entry and + len(entry['service_classes']) == 1 and + 'Unspecified' in entry['service_classes']): + entry['service_classes'] = None return proc_data diff --git a/jc/parsers/history.py b/jc/parsers/history.py index fab1217b..c31c12b5 100644 --- a/jc/parsers/history.py +++ b/jc/parsers/history.py @@ -1,8 +1,12 @@ """jc - JSON CLI output utility `history` command output parser -This parser will output a list of dictionaries each containing `line` and `command` keys. If you would like a simple dictionary output, then use the `-r` command-line option or the `raw=True` argument in the `parse()` function. +This parser will output a list of dictionaries each containing `line` and +`command` keys. If you would like a simple dictionary output, then use the +`-r` command-line option or the `raw=True` argument in the `parse()` +function. -The "Magic" syntax is not supported since the `history` command is a shell builtin. +The "Magic" syntax is not supported since the `history` command is a shell +builtin. Usage (cli): @@ -69,8 +73,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Optimizations by https://github.com/philippeitis' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] diff --git a/jc/parsers/hosts.py b/jc/parsers/hosts.py index 7bc515d3..e29e73e3 100644 --- a/jc/parsers/hosts.py +++ b/jc/parsers/hosts.py @@ -83,8 +83,6 @@ class info(): description = '`/etc/hosts` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] diff --git a/jc/parsers/id.py b/jc/parsers/id.py index 22e174a6..733d4aae 100644 --- a/jc/parsers/id.py +++ b/jc/parsers/id.py @@ -114,9 +114,6 @@ class info(): description = '`id` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] magic_commands = ['id'] diff --git a/jc/parsers/ifconfig.py b/jc/parsers/ifconfig.py index 600b62b1..11db3713 100644 --- a/jc/parsers/ifconfig.py +++ b/jc/parsers/ifconfig.py @@ -198,8 +198,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using ifconfig-parser from https://github.com/KnightWhoSayNi/ifconfig-parser' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'aix', 'freebsd', 'darwin'] magic_commands = ['ifconfig'] @@ -235,10 +233,12 @@ class _IfconfigParser(object): # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - attributes = ['name', 'type', 'mac_addr', 'ipv4_addr', 'ipv4_bcast', 'ipv4_mask', 'ipv6_addr', 'ipv6_mask', - 'ipv6_scope', 'state', 'mtu', 'metric', 'rx_packets', 'rx_errors', 'rx_dropped', 'rx_overruns', - 'rx_frame', 'tx_packets', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier', 'tx_collisions', - 'rx_bytes', 'tx_bytes'] + attributes = [ + 'name', 'type', 'mac_addr', 'ipv4_addr', 'ipv4_bcast', 'ipv4_mask', 'ipv6_addr', + 'ipv6_mask', 'ipv6_scope', 'state', 'mtu', 'metric', 'rx_packets', 'rx_errors', + 'rx_dropped', 'rx_overruns', 'rx_frame', 'tx_packets', 'tx_errors', 'tx_dropped', + 'tx_overruns', 'tx_carrier', 'tx_collisions', 'rx_bytes', 'tx_bytes' + ] def __init__(self, console_output): """ @@ -436,9 +436,11 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ for entry in proc_data: - int_list = ['flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped', 'rx_overruns', - 'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier', - 'tx_collisions', 'metric'] + int_list = [ + 'flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped', + 'rx_overruns', 'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped', + 'tx_overruns', 'tx_carrier', 'tx_collisions', 'metric' + ] for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) diff --git a/jc/parsers/ini.py b/jc/parsers/ini.py index 25fd61a4..7840c726 100644 --- a/jc/parsers/ini.py +++ b/jc/parsers/ini.py @@ -1,8 +1,12 @@ """jc - JSON CLI output utility `INI` file parser -Parses standard `INI` files and files containing simple key/value pairs. Delimiter can be `=` or `:`. Missing values are supported. Comment prefix can be `#` or `;`. Comments must be on their own line. +Parses standard `INI` files and files containing simple key/value pairs. +Delimiter can be `=` or `:`. Missing values are supported. Comment prefix +can be `#` or `;`. Comments must be on their own line. -Note: Values starting and ending with quotation marks will have the marks removed. If you would like to keep the quotation marks, use the `-r` command-line argument or the `raw=True` argument in `parse()`. +Note: Values starting and ending with quotation marks will have the marks +removed. If you would like to keep the quotation marks, use the `-r` +command-line argument or the `raw=True` argument in `parse()`. Usage (cli): @@ -20,11 +24,8 @@ Usage (module): Schema: - ini or key/value document converted to a dictionary - see configparser standard - library documentation for more details. - - Note: Values starting and ending with quotation marks will have the marks removed. - If you would like to keep the quotation marks, use the -r or raw=True argument. + ini or key/value document converted to a dictionary - see the + configparser standard library documentation for more details. { "key1": string, @@ -76,8 +77,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using configparser from the standard library' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] @@ -108,8 +107,12 @@ def _process(proc_data): # simple key/value files with no headers else: - if proc_data[heading] is not None and proc_data[heading].startswith('"') and proc_data[heading].endswith('"'): + if (proc_data[heading] is not None and + proc_data[heading].startswith('"') and + proc_data[heading].endswith('"')): + proc_data[heading] = proc_data[heading].lstrip('"').rstrip('"') + elif proc_data[heading] is None: proc_data[heading] = '' diff --git a/jc/parsers/iostat_s.py b/jc/parsers/iostat_s.py index 52f21aa1..994756fe 100644 --- a/jc/parsers/iostat_s.py +++ b/jc/parsers/iostat_s.py @@ -11,14 +11,16 @@ Usage (cli): Usage (module): import jc - result = jc.parse('iostat_s', iostat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('iostat_s', iostat_command_output.splitlines()) for item in result: # do something or import jc.parsers.iostat_s - result = jc.parsers.iostat_s.parse(iostat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.iostat_s.parse(iostat_command_output.splitlines()) for item in result: # do something @@ -75,9 +77,12 @@ Schema: "percent_util": float, "percent_rrqm": float, "percent_wrqm": float, - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error + "success": boolean, # false if error parsing "error": string, # exists if "success" is false "line": string # exists if "success" is false } @@ -86,13 +91,13 @@ Schema: Examples: $ iostat | jc --iostat-s - {"percent_user":0.14,"percent_nice":0.0,"percent_system":0.16,"percent_iowait":0.0,"percent_steal":0.0,"percent_idle":99.7,"type":"cpu"} - {"device":"sda","tps":0.24,"kb_read_s":5.28,"kb_wrtn_s":1.1,"kb_read":203305,"kb_wrtn":42368,"type":"device"} + {"percent_user":0.14,"percent_nice":0.0,"percent_system":0.16,...} + {"device":"sda","tps":0.24,"kb_read_s":5.28,"kb_wrtn_s":1.1...} ... $ iostat | jc --iostat-s -r - {"percent_user":"0.14","percent_nice":"0.00","percent_system":"0.16","percent_iowait":"0.00","percent_steal":"0.00","percent_idle":"99.70","type":"cpu"} - {"device":"sda","tps":"0.24","kb_read_s":"5.28","kb_wrtn_s":"1.10","kb_read":"203305","kb_wrtn":"42368","type":"device"} + {"percent_user":"0.14","percent_nice":"0.00","percent_system":"0.16"...} + {"device":"sda","tps":"0.24","kb_read_s":"5.28","kb_wrtn_s":"1.10"...} ... """ import jc.utils @@ -160,7 +165,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/iptables.py b/jc/parsers/iptables.py index 4c61db72..6d1fafa4 100644 --- a/jc/parsers/iptables.py +++ b/jc/parsers/iptables.py @@ -172,8 +172,6 @@ class info(): description = '`iptables` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['iptables'] diff --git a/jc/parsers/iw_scan.py b/jc/parsers/iw_scan.py index 73fc811b..733e6573 100644 --- a/jc/parsers/iw_scan.py +++ b/jc/parsers/iw_scan.py @@ -1,6 +1,7 @@ """jc - JSON CLI output utility `iw dev scan` command output parser -This parser is considered beta quality. Not all fields are parsed and there are not enough samples to test. +This parser is considered beta quality. Not all fields are parsed and there +are not enough samples to test. Usage (cli): @@ -24,7 +25,7 @@ Schema: [ { - "foo": string/integer/float, # best guess based on value + "foo": string/integer/float, # best guess based on value "bar": string/integer/float, "baz": string/integer/float } @@ -131,8 +132,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Enhancements by Philipp Schmitt (https://pschmitt.dev/)' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['iw dev'] @@ -325,7 +324,9 @@ def parse(data, raw=False, quiet=False): split_line = line.split(':', maxsplit=1) if len(split_line) == 2: - split_line[0] = split_line[0].lower().replace('*', '').replace('(', '').replace(')', '').replace(',', '').replace('-', '_').strip().replace(' ', '_') + split_line[0] = split_line[0].lower().replace('*', '').replace('(', '')\ + .replace(')', '').replace(',', '').replace('-', '_')\ + .strip().replace(' ', '_') section[split_line[0]] = split_line[1].strip() continue diff --git a/jc/parsers/jar_manifest.py b/jc/parsers/jar_manifest.py index 4423471a..e2b626b3 100644 --- a/jc/parsers/jar_manifest.py +++ b/jc/parsers/jar_manifest.py @@ -26,15 +26,16 @@ Schema: Examples: $ cat MANIFEST.MF | jc --jar-manifest -p - $ unzip -c apache-log4j-2.16.0-bin/log4j-core-2.16.0.jar META-INF/MANIFEST.MF | jc --jar-manifest -p - $ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | jc --jar-manifest -p + $ unzip -c log4j-core-2.16.0.jar META-INF/MANIFEST.MF | \\ + jc --jar-manifest -p + $ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | \\ + jc --jar-manifest -p $ cat MANIFEST.MF | jc --jar-manifest -p - [ { - "Import_Package": "com.conversantmedia.util.concurrent;resolution:=optional,com.fasterxml.jackson.annotation;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.core;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.core.type;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.cor...", - "Export_Package": "org.apache.logging.log4j.core;uses:=\"org.apache.logging.log4j,org.apache.logging.log4j.core.config,org.apache.logging.log4j.core.impl,org.apache.logging.log4j.core.layout,org.apache.logging.log4j.core.time,org.apache.logging.log4j.message,org.apache.logging.log4j.spi,org.apache.logging.log4j.status...", + "Import_Package": "com.conversantmedia.util.concurrent;resoluti...", + "Export_Package": "org.apache.logging.log4j.core;uses:=\"org.ap...", "Manifest_Version": "1.0", "Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt", "Bundle_SymbolicName": "org.apache.logging.log4j.core", @@ -47,28 +48,28 @@ Examples: } ] - $ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | jc --jar-manifest -p - + $ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | \\ + jc --jar-manifest -p [ ... { - "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-sources.jar", + "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-so...", "Manifest_Version": "1.0", "Built_By": "matt", "Created_By": "Apache Maven 3.8.4", "Build_Jdk": "1.8.0_312" }, { - "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-javadoc.jar", + "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-ja...", "Manifest_Version": "1.0", "Built_By": "matt", "Created_By": "Apache Maven 3.8.4", "Build_Jdk": "1.8.0_312" }, { - "Bundle_SymbolicName": "org.apache.logging.log4j.spring-cloud-config-client.logging.log4j.core.util;version=\"[2.16,3)\",org.springframework.boot.autoconfigure.condition,org.springframework.cloud.context.environment,org.springframework.context,org.springframework.stereotype", - "Export_Package": "org.apache.logging.log4j.spring.cloud.config.controller;version=\"2.16.0\"ient", - "Archive": "apache-log4j-2.16.0-bin/log4j-spring-cloud-config-client-2.16.0.jar", + "Bundle_SymbolicName": "org.apache.logging.log4j.spring-cloud-c...", + "Export_Package": "org.apache.logging.log4j.spring.cloud.config...", + "Archive": "apache-log4j-2.16.0-bin/log4j-spring-cloud-config-c...", "Manifest_Version": "1.0", "Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt", ... diff --git a/jc/parsers/jobs.py b/jc/parsers/jobs.py index 2941ca27..47d8dc7e 100644 --- a/jc/parsers/jobs.py +++ b/jc/parsers/jobs.py @@ -2,7 +2,8 @@ Also supports the `-l` option. -The "Magic" syntax is not supported since the `jobs` command is a shell builtin. +The "Magic" syntax is not supported since the `jobs` command is a shell +builtin. Usage (cli): @@ -102,8 +103,6 @@ class info(): description = '`jobs` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['jobs'] diff --git a/jc/parsers/kv.py b/jc/parsers/kv.py index 52c2435c..7322387e 100644 --- a/jc/parsers/kv.py +++ b/jc/parsers/kv.py @@ -1,8 +1,12 @@ """jc - JSON CLI output utility `Key/Value` file parser -Supports files containing simple key/value pairs. Delimiter can be `=` or `:`. Missing values are supported. Comment prefix can be `#` or `;`. Comments must be on their own line. +Supports files containing simple key/value pairs. Delimiter can be `=` or +`:`. Missing values are supported. Comment prefix can be `#` or `;`. +Comments must be on their own line. -Note: Values starting and ending with quotation marks will have the marks removed. If you would like to keep the quotation marks, use the `-r` command-line argument or the `raw=True` argument in `parse()`. +Note: Values starting and ending with quotation marks will have the marks +removed. If you would like to keep the quotation marks, use the `-r` +command-line argument or the `raw=True` argument in `parse()`. Usage (cli): @@ -20,7 +24,8 @@ Usage (module): Schema: - key/value document converted to a dictionary - see configparser standard library documentation for more details. + key/value document converted to a dictionary - see the + configparser standard library documentation for more details. { "key1": string, @@ -57,8 +62,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'This is a wrapper for the INI parser' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] diff --git a/jc/parsers/last.py b/jc/parsers/last.py index bef7904b..9480621e 100644 --- a/jc/parsers/last.py +++ b/jc/parsers/last.py @@ -2,7 +2,9 @@ Supports `-w` and `-F` options. -Calculated epoch time fields are naive (i.e. based on the local time of the system the parser is run on) since there is no timezone information in the `last` command output. +Calculated epoch time fields are naive (i.e. based on the local time of the +system the parser is run on) since there is no timezone information in the +`last` command output. Usage (cli): @@ -32,9 +34,9 @@ Schema: "login": string, "logout": string, "duration": string, - "login_epoch": integer, # (naive) available with last -F option - "logout_epoch": integer, # (naive) available with last -F option - "duration_seconds": integer # available with last -F option + "login_epoch": integer, # (naive) available with last -F option + "logout_epoch": integer, # (naive) available with last -F option + "duration_seconds": integer # available with last -F option } ] @@ -114,8 +116,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Enhancements by https://github.com/zerolagtime' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] magic_commands = ['last', 'lastb'] @@ -203,7 +203,10 @@ def parse(data, raw=False, quiet=False): for entry in cleandata: output_line = {} - if entry.startswith('wtmp begins ') or entry.startswith('btmp begins ') or entry.startswith('utx.log begins '): + if (entry.startswith('wtmp begins ') or + entry.startswith('btmp begins ') or + entry.startswith('utx.log begins ')): + continue entry = entry.replace('system boot', 'system_boot') diff --git a/jc/parsers/ls.py b/jc/parsers/ls.py index 24fca999..2fa42e69 100644 --- a/jc/parsers/ls.py +++ b/jc/parsers/ls.py @@ -4,11 +4,17 @@ Options supported: - `lbaR1` - `--time-style=full-iso` -Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly parse filenames that include newline characters. Since `ls` does not encode newlines in filenames when outputting to a pipe it will cause `jc` to see multiple files instead of a single file if `-1`, `-l`, or `-b` is not used. Alternatively, `vdir` can be used, which is the same as running `ls -lb`. +Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly +parse filenames that include newline characters. Since `ls` does not encode +newlines in filenames when outputting to a pipe it will cause `jc` to see +multiple files instead of a single file if `-1`, `-l`, or `-b` is not used. +Alternatively, `vdir` can be used, which is the same as running `ls -lb`. -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the timezone field is UTC. Usage (cli): @@ -40,11 +46,14 @@ Schema: "group": string, "size": integer, "date": string, - "epoch": integer, # naive timestamp if date field exists and can be converted - "epoch_utc": integer # timezone aware timestamp if date field is in UTC and can be converted + "epoch": integer, # [0] + "epoch_utc": integer # [1] } ] + [0] naive timestamp if date field exists and can be converted + [1] timezone aware timestamp if date field is in UTC and can be converted + Examples: $ ls /usr/bin | jc --ls -p @@ -116,8 +125,6 @@ class info(): description = '`ls` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['ls', 'vdir'] diff --git a/jc/parsers/ls_s.py b/jc/parsers/ls_s.py index c79e5212..2a1e792b 100644 --- a/jc/parsers/ls_s.py +++ b/jc/parsers/ls_s.py @@ -1,14 +1,19 @@ -"""jc - JSON CLI output utility `ls` and `vdir` command output streaming parser +"""jc - JSON CLI output utility `ls` and `vdir` command output streaming +parser > This streaming parser outputs JSON Lines -Requires the `-l` option to be used on `ls`. If there are newline characters in the filename, then make sure to use the `-b` option on `ls`. +Requires the `-l` option to be used on `ls`. If there are newline characters +in the filename, then make sure to use the `-b` option on `ls`. -The `jc` `-qq` option can be used to ignore parsing errors. (e.g. filenames with newline characters, but `-b` was not used) +The `jc` `-qq` option can be used to ignore parsing errors. (e.g. filenames +with newline characters, but `-b` was not used) -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive (i.e. based on the local time +of the system the parser is run on) -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the timezone field is UTC. Usage (cli): @@ -17,14 +22,16 @@ Usage (cli): Usage (module): import jc - result = jc.parse('ls_s', ls_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('ls_s', ls_command_output.splitlines()) for item in result: # do something or import jc.parsers.ls_s - result = jc.parsers.ls_s.parse(ls_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.ls_s.parse(ls_command_output.splitlines()) for item in result: # do something @@ -39,28 +46,34 @@ Schema: "group": string, "size": integer, "date": string, - "epoch": integer, # naive timestamp if date field exists and can be converted - "epoch_utc": integer, # timezone aware timestamp if date field is in UTC and can be converted - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + "epoch": integer, # [0] + "epoch_utc": integer, # [1] + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error + "success": boolean, # false if error parsing "error": string, # exists if "success" is false "line": string # exists if "success" is false } } + [0] naive timestamp if date field exists and can be converted + [1] timezone aware timestamp if date field is in UTC and can be converted + Examples: $ ls -l /usr/bin | jc --ls-s - {"filename":"2to3-","flags":"-rwxr-xr-x","links":4,"owner":"root","group":"wheel","size":925,"date":"Feb 22 2019"} - {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/2to3-2.7","flags":"lrwxr-xr-x","links":1,"owner":"root","group":"wheel","size":74,"date":"May 4 2019"} - {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":1,"owner":"root","group":"wheel","size":55152,"date":"May 3 2019"} + {"filename":"2to3-","flags":"-rwxr-xr-x","links":4,"owner":"root","...} + {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/P...} + {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":1,...} ... $ ls -l /usr/bin | jc --ls-s -r - {"filename":"2to3-","flags":"-rwxr-xr-x","links":"4","owner":"root","group":"wheel","size":"925","date":"Feb 22 2019"} - {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/2to3-2.7","flags":"lrwxr-xr-x","links":"1","owner":"root","group":"wheel","size":"74","date":"May 4 2019"} - {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":"1","owner":"root","group":"wheel","size":"55152","date":"May 3 2019"} + {"filename":"2to3-","flags":"-rwxr-xr-x","links":"4","owner":"roo"..."} + {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/P...} + {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":"1...} ... """ import re @@ -75,8 +88,6 @@ class info(): description = '`ls` command streaming parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] streaming = True @@ -117,7 +128,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/lsblk.py b/jc/parsers/lsblk.py index c4866c74..c1a1907e 100644 --- a/jc/parsers/lsblk.py +++ b/jc/parsers/lsblk.py @@ -90,7 +90,10 @@ Examples: ... ] - $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p + $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,\\ + STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,\\ + SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,\\ + PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p [ { "name": "sda", @@ -179,7 +182,10 @@ Examples: ... ] - $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p -r + $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,\\ + STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,\\ + SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,\\ + PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p -r [ { "name": "sda", @@ -278,8 +284,6 @@ class info(): description = '`lsblk` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['lsblk'] @@ -302,7 +306,8 @@ def _process(proc_data): for entry in proc_data: # boolean and integer changes bool_list = ['rm', 'ro', 'rota', 'disc_zero', 'rand'] - int_list = ['ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', 'rq_size', 'disc_aln'] + int_list = ['ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', + 'rq_size', 'disc_aln'] for key in entry: if key in bool_list: entry[key] = jc.utils.convert_to_bool(entry[key]) diff --git a/jc/parsers/lsmod.py b/jc/parsers/lsmod.py index a42aba37..5e3084ba 100644 --- a/jc/parsers/lsmod.py +++ b/jc/parsers/lsmod.py @@ -135,8 +135,6 @@ class info(): description = '`lsmod` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['lsmod'] diff --git a/jc/parsers/lsof.py b/jc/parsers/lsof.py index a8ea76d7..22bdd04f 100644 --- a/jc/parsers/lsof.py +++ b/jc/parsers/lsof.py @@ -129,8 +129,6 @@ class info(): description = '`lsof` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['lsof'] diff --git a/jc/parsers/lsusb.py b/jc/parsers/lsusb.py index d724ce4c..4df4ab1f 100644 --- a/jc/parsers/lsusb.py +++ b/jc/parsers/lsusb.py @@ -22,8 +22,9 @@ Usage (module): Schema: - Note: object keynames are assigned directly from the lsusb output. - If there are duplicate names in a section, only the last one is converted. + Note: object keynames are assigned directly from the lsusb + output. If there are duplicate names in a section, only the + last one is converted. [ { diff --git a/jc/parsers/mount.py b/jc/parsers/mount.py index 019e0def..49bf44cd 100644 --- a/jc/parsers/mount.py +++ b/jc/parsers/mount.py @@ -84,8 +84,6 @@ class info(): description = '`mount` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['mount'] diff --git a/jc/parsers/netstat.py b/jc/parsers/netstat.py index 537ce8e4..f2e1ad73 100644 --- a/jc/parsers/netstat.py +++ b/jc/parsers/netstat.py @@ -2,7 +2,8 @@ Caveats: - Use of multiple `l` options is not supported on OSX (e.g. `netstat -rlll`) -- Use of the `A` option is not supported on OSX when using the `r` option (e.g. `netstat -rA`) +- Use of the `A` option is not supported on OSX when using the `r` option + (e.g. `netstat -rA`) Usage (cli): @@ -363,8 +364,6 @@ class info(): description = '`netstat` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['netstat'] @@ -386,13 +385,14 @@ def _process(proc_data): """ for entry in proc_data: # integer and float conversions - int_list = ['recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class', - 'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes', - 'route_refs', 'use', 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts', - 'ierrs', 'opkts', 'oerrs', 'coll', 'rx_ok', 'rx_err', 'rx_drp', 'rx_ovr', - 'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop', 'ibytes', 'obytes', 'r_mbuf', - 's_mbuf', 'r_clus', 's_clus', 'r_hiwa', 's_hiwa', 'r_lowa', 's_lowa', 'r_bcnt', - 's_bcnt', 'r_bmax', 's_bmax', 'rexmit', 'ooorcv', '0_win'] + int_list = [ + 'recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class', 'osx_flags', + 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes', 'route_refs', 'use', + 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts', 'ierrs', 'opkts', 'oerrs', 'coll', + 'rx_ok', 'rx_err', 'rx_drp', 'rx_ovr', 'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop', + 'ibytes', 'obytes', 'r_mbuf', 's_mbuf', 'r_clus', 's_clus', 'r_hiwa', 's_hiwa', + 'r_lowa', 's_lowa', 'r_bcnt', 's_bcnt', 'r_bmax', 's_bmax', 'rexmit', 'ooorcv', '0_win' + ] float_list = ['rexmt', 'persist', 'keep', '2msl', 'delack', 'rcvtime'] for key in entry: if key in int_list: diff --git a/jc/parsers/ntpq.py b/jc/parsers/ntpq.py index 75a92463..9408a1c1 100644 --- a/jc/parsers/ntpq.py +++ b/jc/parsers/ntpq.py @@ -216,8 +216,6 @@ class info(): description = '`ntpq -p` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'freebsd'] magic_commands = ['ntpq'] diff --git a/jc/parsers/passwd.py b/jc/parsers/passwd.py index 578ce259..ad2756a9 100644 --- a/jc/parsers/passwd.py +++ b/jc/parsers/passwd.py @@ -103,9 +103,6 @@ class info(): description = '`/etc/passwd` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] diff --git a/jc/parsers/ping.py b/jc/parsers/ping.py index aca63adf..322289dc 100644 --- a/jc/parsers/ping.py +++ b/jc/parsers/ping.py @@ -4,7 +4,8 @@ Supports `ping` and `ping6` output. Usage (cli): - Note: Use the ping `-c` (count) option, otherwise data will not be piped to `jc`. + Note: Use the ping `-c` (count) option, otherwise data will not be + piped to `jc`. $ ping -c 3 1.2.3.4 | jc --ping @@ -28,7 +29,7 @@ Schema: "source_ip": string, "destination_ip": string, "data_bytes": integer, - "pattern": string, # (null if not set) + "pattern": string, # null if not set "destination": string, "packets_transmitted": integer, "packets_received": integer, @@ -40,8 +41,8 @@ Schema: "round_trip_ms_stddev": float, "responses": [ { - "type": string, # 'reply', 'timeout', 'unparsable_line', etc. See `_error_type.type_map` for all options - "unparsed_line": string, # only if an 'unparsable_line' type + "type": string, # [0] + "unparsed_line": string, # [1] "timestamp": float, "bytes": integer, "response_ip": string, @@ -49,21 +50,26 @@ Schema: "ttl": integer, "time_ms": float, "duplicate": boolean, - "vr": integer, # hex value converted to decimal - "hl": integer, # hex value converted to decimal - "tos": integer, # hex value converted to decimal - "len": integer, # hex value converted to decimal - "id": integer, # hex value converted to decimal - "flg": integer, # hex value converted to decimal - "off": integer, # hex value converted to decimal - "pro": integer, # hex value converted to decimal - "cks": ingeger, # hex value converted to decimal + "vr": integer, # [2] + "hl": integer, # [2] + "tos": integer, # [2] + "len": integer, # [2] + "id": integer, # [2] + "flg": integer, # [2] + "off": integer, # [2] + "pro": integer, # [2] + "cks": ingeger, # [2] "src": string, "dst": string } ] } + [0] 'reply', 'timeout', 'unparsable_line', etc. See + `_error_type.type_map` for all options + [1] only if an 'unparsable_line' type + [2] hex value converted to decimal + Examples: $ ping -c 3 -p ff cnn.com | jc --ping -p @@ -167,8 +173,6 @@ class info(): description = '`ping` and `ping6` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['ping', 'ping6'] @@ -188,10 +192,14 @@ def _process(proc_data): Dictionary. Structured data to conform to the schema. """ - int_list = ['data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl', - 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'] - float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', - 'round_trip_ms_stddev', 'timestamp', 'time_ms'] + int_list = [ + 'data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl', + 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks' + ] + float_list = [ + 'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', + 'round_trip_ms_stddev', 'timestamp', 'time_ms' + ] for key in proc_data: if key in int_list: diff --git a/jc/parsers/ping_s.py b/jc/parsers/ping_s.py index 1f64af14..0a76b6de 100644 --- a/jc/parsers/ping_s.py +++ b/jc/parsers/ping_s.py @@ -8,66 +8,79 @@ Usage (cli): $ ping | jc --ping-s -> Note: When piping `jc` converted `ping` output to other processes it may appear the output is hanging due to the OS pipe buffers. This is because `ping` output is too small to quickly fill up the buffer. Use the `-u` option to unbuffer the `jc` output if you would like immediate output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) for more information. +> Note: When piping `jc` converted `ping` output to other processes it may + appear the output is hanging due to the OS pipe buffers. This is because + `ping` output is too small to quickly fill up the buffer. Use the `-u` + option to unbuffer the `jc` output if you would like immediate output. + See the[readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) + for more information. Usage (module): import jc - result = jc.parse('ping_s', ping_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('ping_s', ping_command_output.splitlines()) for item in result: # do something or import jc.parsers.ping_s - result = jc.parsers.ping_s.parse(ping_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.ping_s.parse(ping_command_output.splitlines()) for item in result: # do something Schema: { - "type": string, # 'reply', 'timeout', 'summary', etc. See `_error_type.type_map` for all options. - "source_ip": string, - "destination_ip": string, - "sent_bytes": integer, - "pattern": string, # (null if not set) - "destination": string, - "timestamp": float, - "response_bytes": integer, - "response_ip": string, - "icmp_seq": integer, - "ttl": integer, - "time_ms": float, - "duplicate": boolean, - "packets_transmitted": integer, - "packets_received": integer, - "packet_loss_percent": float, - "duplicates": integer, - "round_trip_ms_min": float, - "round_trip_ms_avg": float, - "round_trip_ms_max": float, - "round_trip_ms_stddev": float, - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + "type": string, # [0] + "source_ip": string, + "destination_ip": string, + "sent_bytes": integer, + "pattern": string, # (null if not set) + "destination": string, + "timestamp": float, + "response_bytes": integer, + "response_ip": string, + "icmp_seq": integer, + "ttl": integer, + "time_ms": float, + "duplicate": boolean, + "packets_transmitted": integer, + "packets_received": integer, + "packet_loss_percent": float, + "duplicates": integer, + "round_trip_ms_min": float, + "round_trip_ms_avg": float, + "round_trip_ms_max": float, + "round_trip_ms_stddev": float, + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error - "error": string, # exists if "success" is false - "line": string # exists if "success" is false + "success": boolean, # false if error parsing + "error": string, # exists if "success" is false + "line": string # exists if "success" is false } } + [0] 'reply', 'timeout', 'summary', etc. See `_error_type.type_map` + for all options. + Examples: $ ping 1.1.1.1 | jc --ping-s - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":0,"ttl":56,"time_ms":23.703} - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":1,"ttl":56,"time_ms":22.862} - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":2,"ttl":56,"time_ms":22.82} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...} ... $ ping 1.1.1.1 | jc --ping-s -r - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"0","ttl":"56","time_ms":"23.054"} - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"1","ttl":"56","time_ms":"24.739"} - {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"2","ttl":"56","time_ms":"23.232"} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...} + {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...} ... """ import string @@ -83,8 +96,6 @@ class info(): description = '`ping` and `ping6` command streaming parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] streaming = True @@ -104,10 +115,14 @@ def _process(proc_data): Dictionary. Structured data to conform to the schema. """ - int_list = ['sent_bytes', 'packets_transmitted', 'packets_received', 'response_bytes', 'icmp_seq', 'ttl', - 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'] - float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', - 'round_trip_ms_stddev', 'timestamp', 'time_ms'] + int_list = [ + 'sent_bytes', 'packets_transmitted', 'packets_received', 'response_bytes', 'icmp_seq', + 'ttl', 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks' + ] + float_list = [ + 'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', + 'round_trip_ms_stddev', 'timestamp', 'time_ms' + ] for key in proc_data: if key in int_list: @@ -460,7 +475,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/pip_list.py b/jc/parsers/pip_list.py index 6c569318..a5583930 100644 --- a/jc/parsers/pip_list.py +++ b/jc/parsers/pip_list.py @@ -57,8 +57,6 @@ class info(): description = '`pip list` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] magic_commands = ['pip list', 'pip3 list'] diff --git a/jc/parsers/pip_show.py b/jc/parsers/pip_show.py index b5a6bc95..22fd9647 100644 --- a/jc/parsers/pip_show.py +++ b/jc/parsers/pip_show.py @@ -74,8 +74,6 @@ class info(): description = '`pip show` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] magic_commands = ['pip show', 'pip3 show'] diff --git a/jc/parsers/ps.py b/jc/parsers/ps.py index 16346674..59f0c4c2 100644 --- a/jc/parsers/ps.py +++ b/jc/parsers/ps.py @@ -58,7 +58,7 @@ Examples: "stime": "Nov01", "tty": null, "time": "00:00:11", - "cmd": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" + "cmd": "/usr/lib/systemd/systemd --switched-root --system --dese..." }, { "uid": "root", @@ -93,7 +93,7 @@ Examples: "stime": "Nov01", "tty": "?", "time": "00:00:11", - "cmd": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" + "cmd": "/usr/lib/systemd/systemd --switched-root --system --dese..." }, { "uid": "root", @@ -131,7 +131,7 @@ Examples: "stat": "Ss", "start": "Nov09", "time": "0:08", - "command": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" + "command": "/usr/lib/systemd/systemd --switched-root --system --..." }, { "user": "root", @@ -175,7 +175,7 @@ Examples: "stat": "Ss", "start": "Nov09", "time": "0:08", - "command": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" + "command": "/usr/lib/systemd/systemd --switched-root --system --..." }, { "user": "root", @@ -216,8 +216,6 @@ class info(): description = '`ps` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['ps'] diff --git a/jc/parsers/route.py b/jc/parsers/route.py index e4f21f68..ee7788cc 100644 --- a/jc/parsers/route.py +++ b/jc/parsers/route.py @@ -118,8 +118,6 @@ class info(): description = '`route` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['route'] @@ -197,7 +195,9 @@ def parse(data, raw=False, quiet=False): # fixup header row for ipv6 if ' Next Hop ' in cleandata[0]: cleandata[0] = cleandata[0].replace(' If', ' Iface') - cleandata[0] = cleandata[0].replace(' Next Hop ', ' Next_Hop ').replace(' Flag ', ' Flags ').replace(' Met ', ' Metric ') + cleandata[0] = cleandata[0].replace(' Next Hop ', ' Next_Hop ')\ + .replace(' Flag ', ' Flags ')\ + .replace(' Met ', ' Metric ') cleandata[0] = cleandata[0].lower() raw_output = jc.parsers.universal.simple_table_parse(cleandata) diff --git a/jc/parsers/rpm_qi.py b/jc/parsers/rpm_qi.py index 7f43aa88..9453d6ca 100644 --- a/jc/parsers/rpm_qi.py +++ b/jc/parsers/rpm_qi.py @@ -2,9 +2,11 @@ Works with `rpm -qi [package]` or `rpm -qia`. -The `..._epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) +The `..._epoch` calculated timestamp fields are naive. (i.e. based on the +local time of the system the parser is run on) -The `..._epoch_utc` calculated timestamp fields are timezone-aware and is only available if the timezone field is UTC. +The `..._epoch_utc` calculated timestamp fields are timezone-aware and is +only available if the timezone field is UTC. Usage (cli): @@ -34,16 +36,16 @@ Schema: "release": string, "architecture": string, "install_date": string, - "install_date_epoch": integer, # naive timestamp - "install_date_epoch_utc": integer, # Aware timestamp if timezone is UTC + "install_date_epoch": integer, # [0] + "install_date_epoch_utc": integer, # [1] "group": string, "size": integer, "license": string, "signature": string, "source_rpm": string, "build_date": string, - "build_epoch": integer, # naive timestamp - "build_epoch_utc": integer, # Aware timestamp if timezone is UTC + "build_epoch": integer, # [0] + "build_epoch_utc": integer, # [1] "build_host": string, "relocations": string, "packager": string, @@ -54,6 +56,9 @@ Schema: } ] + [0] naive timestamp + [1] Aware timestamp if timezone is UTC + Examples: $ rpm -qia | jc --rpm-qi -p @@ -68,7 +73,7 @@ Examples: "group": "Development/Tools", "size": 1160660, "license": "GPLv2+", - "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ID 24c6a8a7f4a80eb5", + "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ...", "source_rpm": "make-3.82-24.el7.src.rpm", "build_date": "Thu 08 Aug 2019 05:47:25 PM PDT", "build_host": "x86-01.bsys.centos.org", @@ -76,8 +81,8 @@ Examples: "packager": "CentOS BuildSystem ", "vendor": "CentOS", "url": "http://www.gnu.org/software/make/", - "summary": "A GNU tool which simplifies the build process for users", - "description": "A GNU tool for controlling the generation of executables and other...", + "summary": "A GNU tool which simplifies the build process for ...", + "description": "A GNU tool for controlling the generation of ex...", "build_epoch": 1565311645, "build_epoch_utc": null, "install_date_epoch": 1571242902, @@ -92,7 +97,7 @@ Examples: "group": "System Environment/Base", "size": 503608, "license": "GPLv2+", - "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ID 24c6a8a7f4a80eb5", + "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ...", "source_rpm": "kbd-1.15.5-15.el7.src.rpm", "build_date": "Tue 30 Oct 2018 03:40:00 PM PDT", "build_host": "x86-01.bsys.centos.org", @@ -101,7 +106,7 @@ Examples: "vendor": "CentOS", "url": "http://ftp.altlinux.org/pub/people/legion/kbd", "summary": "Legacy data for kbd package", - "description": "The kbd-legacy package contains original keymaps for kbd package...", + "description": "The kbd-legacy package contains original keymap...", "build_epoch": 1540939200, "build_epoch_utc": null, "install_date_epoch": 1565891588, @@ -122,7 +127,7 @@ Examples: "group": "Development/Tools", "size": "1160660", "license": "GPLv2+", - "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ID 24c6a8a7f4a80eb5", + "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ...", "source_rpm": "make-3.82-24.el7.src.rpm", "build_date": "Thu 08 Aug 2019 05:47:25 PM PDT", "build_host": "x86-01.bsys.centos.org", @@ -130,8 +135,8 @@ Examples: "packager": "CentOS BuildSystem ", "vendor": "CentOS", "url": "http://www.gnu.org/software/make/", - "summary": "A GNU tool which simplifies the build process for users", - "description": "A GNU tool for controlling the generation of executables and other..." + "summary": "A GNU tool which simplifies the build process for...", + "description": "A GNU tool for controlling the generation of exe..." }, { "name": "kbd-legacy", @@ -142,7 +147,7 @@ Examples: "group": "System Environment/Base", "size": "503608", "license": "GPLv2+", - "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ID 24c6a8a7f4a80eb5", + "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ...", "source_rpm": "kbd-1.15.5-15.el7.src.rpm", "build_date": "Tue 30 Oct 2018 03:40:00 PM PDT", "build_host": "x86-01.bsys.centos.org", @@ -151,7 +156,7 @@ Examples: "vendor": "CentOS", "url": "http://ftp.altlinux.org/pub/people/legion/kbd", "summary": "Legacy data for kbd package", - "description": "The kbd-legacy package contains original keymaps for kbd package..." + "description": "The kbd-legacy package contains original keymaps..." }, ... ] @@ -165,9 +170,6 @@ class info(): description = '`rpm -qi` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['rpm -qi', 'rpm -qia', 'rpm -qai'] diff --git a/jc/parsers/sfdisk.py b/jc/parsers/sfdisk.py index 4ec88d6e..858bd743 100644 --- a/jc/parsers/sfdisk.py +++ b/jc/parsers/sfdisk.py @@ -55,7 +55,7 @@ Schema: "boot": boolean, "start": integer, "end": integer, - "size": string, # Note: will be integer when using deprecated -d sfdisk option + "size": string, # [0] "cyls": integer, "mib": integer, "blocks": integer, @@ -68,6 +68,8 @@ Schema: } ] + [0] will be integer when using deprecated -d sfdisk option + Examples: # sfdisk -l | jc --sfdisk -p @@ -77,7 +79,7 @@ Examples: "cylinders": 2610, "heads": 255, "sectors_per_track": 63, - "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0", + "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, ...", "partitions": [ { "device": "/dev/sda1", @@ -142,7 +144,7 @@ Examples: "cylinders": "2610", "heads": "255", "sectors_per_track": "63", - "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0", + "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, co...", "partitions": [ { "device": "/dev/sda1", @@ -229,9 +231,11 @@ def _process(proc_data): List of Dictionaries. Structured to conform to the schema. """ - int_list = ['cylinders', 'heads', 'sectors_per_track', 'start', 'end', 'cyls', 'mib', - 'blocks', 'sectors', 'bytes', 'logical_sector_size', 'physical_sector_size', - 'min_io_size', 'optimal_io_size', 'free_bytes', 'free_sectors'] + int_list = [ + 'cylinders', 'heads', 'sectors_per_track', 'start', 'end', 'cyls', 'mib', 'blocks', + 'sectors', 'bytes', 'logical_sector_size', 'physical_sector_size', 'min_io_size', + 'optimal_io_size', 'free_bytes', 'free_sectors' + ] bool_list = ['boot'] for entry in proc_data: diff --git a/jc/parsers/shadow.py b/jc/parsers/shadow.py index f390d49c..0e7021fa 100644 --- a/jc/parsers/shadow.py +++ b/jc/parsers/shadow.py @@ -110,9 +110,6 @@ class info(): description = '`/etc/shadow` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'aix', 'freebsd'] diff --git a/jc/parsers/ss.py b/jc/parsers/ss.py index 789574f6..cdc2b8e0 100644 --- a/jc/parsers/ss.py +++ b/jc/parsers/ss.py @@ -1,6 +1,7 @@ """jc - JSON CLI output utility `ss` command output parser -Extended information options like -e and -p are not supported and may cause parsing irregularities. +Extended information options like -e and -p are not supported and may cause +parsing irregularities. Usage (cli): @@ -22,7 +23,8 @@ Usage (module): Schema: - Information from https://www.cyberciti.biz/files/ss.html used to define field names + Information from https://www.cyberciti.biz/files/ss.html used to define + field names [ { @@ -288,8 +290,6 @@ class info(): description = '`ss` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['ss'] diff --git a/jc/parsers/stat.py b/jc/parsers/stat.py index 5ca06200..c3f20582 100644 --- a/jc/parsers/stat.py +++ b/jc/parsers/stat.py @@ -1,8 +1,10 @@ """jc - JSON CLI output utility `stat` command output parser -The `xxx_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) +The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the +local time of the system the parser is run on) -The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. +The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are +only available if the timezone field is UTC. Usage (cli): @@ -178,8 +180,6 @@ class info(): description = '`stat` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['stat'] @@ -200,8 +200,8 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ for entry in proc_data: - int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device', - 'rdev', 'block_size'] + int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', + 'unix_device', 'rdev', 'block_size'] for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) diff --git a/jc/parsers/stat_s.py b/jc/parsers/stat_s.py index 74c737e2..9a18a228 100644 --- a/jc/parsers/stat_s.py +++ b/jc/parsers/stat_s.py @@ -2,9 +2,11 @@ > This streaming parser outputs JSON Lines -The `xxx_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on). +The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the +local time of the system the parser is run on). -The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. +The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are +only available if the timezone field is UTC. Usage (cli): @@ -13,14 +15,16 @@ Usage (cli): Usage (module): import jc - result = jc.parse('stat_s', stat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('stat_s', stat_command_output.splitlines()) for item in result: # do something or import jc.parsers.stat_s - result = jc.parsers.stat_s.parse(stat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.stat_s.parse(stat_command_output.splitlines()) for item in result: # do something @@ -58,9 +62,12 @@ Schema: "rdev": integer, "block_size": integer, "unix_flags": string, - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error + "success": boolean, # false if error parsing "error": string, # exists if "success" is false "line": string # exists if "success" is false } @@ -69,10 +76,10 @@ Schema: Examples: $ stat | jc --stat-s - {"file":"(stdin)","unix_device":1027739696,"inode":1155,"flags":"crw--w----","links":1,"user":"kbrazil","group":"tty","rdev":268435456,"size":0,"access_time":"Jan 4 15:27:44 2022","modify_time":"Jan 4 15:27:44 2022","change_time":"Jan 4 15:27:44 2022","birth_time":"Dec 31 16:00:00 1969","block_size":131072,"blocks":0,"unix_flags":"0","access_time_epoch":1641338864,"access_time_epoch_utc":null,"modify_time_epoch":1641338864,"modify_time_epoch_utc":null,"change_time_epoch":1641338864,"change_time_epoch_utc":null,"birth_time_epoch":null,"birth_time_epoch_utc":null} + {"file":"(stdin)","unix_device":1027739696,"inode":1155,"flags":"cr...} $ stat | jc --stat-s -r - {"file":"(stdin)","unix_device":"1027739696","inode":"1155","flags":"crw--w----","links":"1","user":"kbrazil","group":"tty","rdev":"268435456","size":"0","access_time":"Jan 4 15:28:08 2022","modify_time":"Jan 4 15:28:08 2022","change_time":"Jan 4 15:28:08 2022","birth_time":"Dec 31 16:00:00 1969","block_size":"131072","blocks":"0","unix_flags":"0"} + {"file":"(stdin)","unix_device":"1027739696","inode":"1155","flag...} """ import shlex import jc.utils @@ -105,8 +112,8 @@ def _process(proc_data): Dictionary. Structured data to conform to the schema. """ - int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device', - 'rdev', 'block_size'] + int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', + 'unix_device', 'rdev', 'block_size'] for key in proc_data: if key in int_list: proc_data[key] = jc.utils.convert_to_int(proc_data[key]) @@ -129,7 +136,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/sysctl.py b/jc/parsers/sysctl.py index 5373c543..7f664d1a 100644 --- a/jc/parsers/sysctl.py +++ b/jc/parsers/sysctl.py @@ -1,6 +1,9 @@ """jc - JSON CLI output utility `sysctl -a` command output parser -Note: Since `sysctl` output is not easily parsable only a very simple key/value object will be output. An attempt is made to convert obvious integers and floats. If no conversion is desired, use the `-r` command-line argument or the `raw=True` argument in `parse()`. +Note: Since `sysctl` output is not easily parsable only a very simple + key/value object will be output. An attempt is made to convert obvious + integers and floats. If no conversion is desired, use the `-r` + command-line argument or the `raw=True` argument in `parse()`. Usage (cli): @@ -23,7 +26,7 @@ Usage (module): Schema: { - "key1": string/integer/float, # best guess based on value + "key1": string/integer/float, # best guess based on value "key2": string/integer/float, "key3": string/integer/float } @@ -63,9 +66,6 @@ class info(): description = '`sysctl` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['sysctl'] diff --git a/jc/parsers/systemctl.py b/jc/parsers/systemctl.py index 7a459e54..b7d9c4ca 100644 --- a/jc/parsers/systemctl.py +++ b/jc/parsers/systemctl.py @@ -39,14 +39,14 @@ Examples: "load": "loaded", "active": "active", "sub": "waiting", - "description": "Arbitrary Executable File Formats File System Automount Point" + "description": "Arbitrary Executable File Formats File System ..." }, { "unit": "dev-block-8:2.device", "load": "loaded", "active": "active", "sub": "plugged", - "description": "LVM PV 3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM on /dev/sda2 2" + "description": "LVM PV 3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM o..." }, { "unit": "dev-cdrom.device", @@ -67,8 +67,6 @@ class info(): description = '`systemctl` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['systemctl'] diff --git a/jc/parsers/systemctl_lj.py b/jc/parsers/systemctl_lj.py index 45317484..0ea2d49d 100644 --- a/jc/parsers/systemctl_lj.py +++ b/jc/parsers/systemctl_lj.py @@ -84,8 +84,6 @@ class info(): description = '`systemctl list-jobs` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['systemctl list-jobs'] diff --git a/jc/parsers/systemctl_ls.py b/jc/parsers/systemctl_ls.py index 1d99dc14..3a3149a0 100644 --- a/jc/parsers/systemctl_ls.py +++ b/jc/parsers/systemctl_ls.py @@ -1,4 +1,5 @@ -"""jc - JSON CLI output utility `systemctl list-sockets` command output parser +"""jc - JSON CLI output utility `systemctl list-sockets` command output +parser Usage (cli): @@ -59,8 +60,6 @@ class info(): description = '`systemctl list-sockets` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['systemctl list-sockets'] diff --git a/jc/parsers/systemctl_luf.py b/jc/parsers/systemctl_luf.py index b09a67b4..3a78e91c 100644 --- a/jc/parsers/systemctl_luf.py +++ b/jc/parsers/systemctl_luf.py @@ -1,4 +1,5 @@ -"""jc - JSON CLI output utility `systemctl list-unit-files` command output parser +"""jc - JSON CLI output utility `systemctl list-unit-files` command output +parser Usage (cli): @@ -55,8 +56,6 @@ class info(): description = '`systemctl list-unit-files` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['systemctl list-unit-files'] diff --git a/jc/parsers/systeminfo.py b/jc/parsers/systeminfo.py index 322e8398..a17a2017 100644 --- a/jc/parsers/systeminfo.py +++ b/jc/parsers/systeminfo.py @@ -2,9 +2,13 @@ Blank or missing elements are set to `null`. -The `original_install_date_epoch` and `system_boot_time_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) +The `original_install_date_epoch` and `system_boot_time_epoch` calculated +timestamp fields are naive. (i.e. based on the local time of the system the +parser is run on) -The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. +The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc` +calculated timestamp fields are timezone-aware and are only available if +the timezone field is UTC. Usage (cli): @@ -33,11 +37,11 @@ Schema: "registered_organization": string, "product_id": string, "original_install_date": string, - "original_install_date_epoch": integer, # naive timestamp - "original_install_date_epoch_utc": integer, # timezone-aware timestamp + "original_install_date_epoch": integer, # [0] + "original_install_date_epoch_utc": integer, # [1] "system_boot_time": string, - "system_boot_time_epoch": integer, # naive timestamp - "system_boot_time_epoch_utc": integer, # timezone-aware timestamp + "system_boot_time_epoch": integer, # [0] + "system_boot_time_epoch_utc": integer, # [1] "system_manufacturer": string, "system_model": string, "system_type": string, @@ -82,6 +86,9 @@ Schema: } } + [0] naive timestamp + [1] timezone-aware timestamp + Examples: $ systeminfo | jc --systeminfo -p @@ -214,9 +221,6 @@ class info: description = "`systeminfo` command parser" author = "Jon Smith" author_email = "jon@rebelliondefense.com" - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ["win32"] magic_commands = ["systeminfo"] @@ -234,11 +238,12 @@ def _process(proc_data): Returns: - Dictionary. Some keys are optional. Example: a system without hyper-v capabilities - will not have a 'hyperv_requirements' key, and a system already running hyper-v - will have an empty "hyperv_requirements" object. + Dictionary. Structured data to conform to the schema. - Structured data to conform to the schema. + Some keys are optional. For example, a system without + hyper-v capabilities will not have a 'hyperv_requirements' key, and + a system already running hyper-v will have an empty + "hyperv_requirements" object. """ # convert empty strings to None/null for item in proc_data: diff --git a/jc/parsers/time.py b/jc/parsers/time.py index fefeed14..977a0f0e 100644 --- a/jc/parsers/time.py +++ b/jc/parsers/time.py @@ -1,14 +1,18 @@ """jc - JSON CLI output utility `/usr/bin/time` command output parser -Output from `/usr/bin/time` is sent to `STDERR`, so the `-o` option can be used to redirect the output to a file that can be read by `jc`. +Output from `/usr/bin/time` is sent to `STDERR`, so the `-o` option can be +used to redirect the output to a file that can be read by `jc`. -Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT` so `jc` can receive it. +Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT` +so `jc` can receive it. -Note: `/usr/bin/time` is similar but different from the Bash builtin `time` command. +Note: `/usr/bin/time` is similar but different from the Bash builtin + `time` command. Usage (cli): - $ /usr/bin/time -o timefile.out sleep 2.5; cat timefile.out | jc --time -p + $ /usr/bin/time -o timefile.out sleep 2; cat timefile.out | \\ + jc --time -p Usage (module): @@ -41,8 +45,8 @@ Schema: "average_unshared_stack_size": integer, "average_shared_memory_size": integer, "maximum_resident_set_size": integer, - "block_input_operations": integer, # aka File system inputs - "block_output_operations": integer, # aka File system outputs + "block_input_operations": integer, # [0] + "block_output_operations": integer, # [1] "major_pagefaults": integer, "minor_pagefaults": integer, "swaps": integer, @@ -62,15 +66,19 @@ Schema: "exit_status": integer } + [0] aka File system inputs + [1] aka File system outputs + Examples: - $ /usr/bin/time --verbose -o timefile.out sleep 2.5; cat timefile.out | jc --time -p + $ /usr/bin/time --verbose -o timefile.out sleep 2; cat timefile.out | \\ + jc --time -p { - "command_being_timed": "sleep 2.5", + "command_being_timed": "sleep 2", "user_time": 0.0, "system_time": 0.0, "cpu_percent": 0, - "elapsed_time": "0:02.50", + "elapsed_time": "0:02.00", "average_shared_text_size": 0, "average_unshared_data_size": 0, "average_stack_size": 0, @@ -96,13 +104,14 @@ Examples: "elapsed_time_total_seconds": 2.5 } - $ /usr/bin/time --verbose -o timefile.out sleep 2.5; cat timefile.out | jc --time -p -r + $ /usr/bin/time --verbose -o timefile.out sleep 2; cat timefile.out | \\ + jc --time -p -r { - "command_being_timed": "\"sleep 2.5\"", + "command_being_timed": "\"sleep 2\"", "user_time": "0.00", "system_time": "0.00", "cpu_percent": "0", - "elapsed_time": "0:02.50", + "elapsed_time": "0:02.00", "average_shared_text_size": "0", "average_unshared_data_size": "0", "average_stack_size": "0", @@ -132,9 +141,6 @@ class info(): description = '`/usr/bin/time` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] @@ -173,12 +179,15 @@ def _process(proc_data): (proc_data['elapsed_time_centiseconds'] / 100) # convert ints and floats - int_list = ['cpu_percent', 'average_shared_text_size', 'average_unshared_data_size', 'average_unshared_stack_size', - 'average_shared_memory_size', 'maximum_resident_set_size', 'block_input_operations', - 'block_output_operations', 'major_pagefaults', 'minor_pagefaults', 'swaps', 'page_reclaims', - 'page_faults', 'messages_sent', 'messages_received', 'signals_received', 'voluntary_context_switches', - 'involuntary_context_switches', 'average_stack_size', 'average_total_size', 'average_resident_set_size', - 'signals_delivered', 'page_size', 'exit_status'] + int_list = [ + 'cpu_percent', 'average_shared_text_size', 'average_unshared_data_size', + 'average_unshared_stack_size', 'average_shared_memory_size', 'maximum_resident_set_size', + 'block_input_operations', 'block_output_operations', 'major_pagefaults', 'minor_pagefaults', + 'swaps', 'page_reclaims', 'page_faults', 'messages_sent', 'messages_received', + 'signals_received', 'voluntary_context_switches', 'involuntary_context_switches', + 'average_stack_size', 'average_total_size', 'average_resident_set_size', + 'signals_delivered', 'page_size', 'exit_status' + ] float_list = ['real_time', 'user_time', 'system_time'] for key in proc_data: if key in int_list: diff --git a/jc/parsers/timedatectl.py b/jc/parsers/timedatectl.py index 593da1ae..3ee05d68 100644 --- a/jc/parsers/timedatectl.py +++ b/jc/parsers/timedatectl.py @@ -1,6 +1,7 @@ """jc - JSON CLI output utility `timedatectl` command output parser -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the `universal_time` field is available. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the `universal_time` field is available. Usage (cli): @@ -25,7 +26,7 @@ Schema: { "local_time": string, "universal_time": string, - "epoch_utc": integer, # timezone-aware timestamp + "epoch_utc": integer, # timezone-aware "rtc_time": string, "time_zone": string, "ntp_enabled": boolean, @@ -72,9 +73,6 @@ class info(): description = '`timedatectl status` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['timedatectl', 'timedatectl status'] diff --git a/jc/parsers/tracepath.py b/jc/parsers/tracepath.py index ac4ca2c1..85a02067 100644 --- a/jc/parsers/tracepath.py +++ b/jc/parsers/tracepath.py @@ -141,8 +141,6 @@ class info(): description = '`tracepath` and `tracepath6` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['tracepath', 'tracepath6'] diff --git a/jc/parsers/traceroute.py b/jc/parsers/traceroute.py index 1f0e57d9..062638db 100644 --- a/jc/parsers/traceroute.py +++ b/jc/parsers/traceroute.py @@ -2,7 +2,10 @@ Supports `traceroute` and `traceroute6` output. -Note: On some operating systems you will need to redirect `STDERR` to `STDOUT` for destination info since the header line is sent to `STDERR`. A warning message will be printed to `STDERR` if the header row is not found. +Note: On some operating systems you will need to redirect `STDERR` to + `STDOUT` for destination info since the header line is sent to + `STDERR`. A warning message will be printed to `STDERR` if the + header row is not found. e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute` @@ -129,8 +132,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using the trparse library by Luis Benitez at https://github.com/lbenitez000/trparse' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['traceroute', 'traceroute6'] diff --git a/jc/parsers/ufw.py b/jc/parsers/ufw.py index e4291cda..e6366bd7 100644 --- a/jc/parsers/ufw.py +++ b/jc/parsers/ufw.py @@ -45,7 +45,7 @@ Schema: "end": integer } ], - "to_service": string, # null if any to ports or port_ranges are set + "to_service": string, # [0] "from_ip": string, "from_ip_prefix": integer, "from_interface": string, @@ -59,12 +59,15 @@ Schema: "end": integer } ], - "from_service": string, # null if any from ports or port_ranges are set + "from_service": string, # [1] "comment": string # null if no comment } ] } + [0] null if any 'to' ports or port_ranges are set + [1] null if any 'from' ports or port_ranges are set + Examples: $ ufw status verbose | jc --ufw -p diff --git a/jc/parsers/ufw_appinfo.py b/jc/parsers/ufw_appinfo.py index 1f06991a..c34ef8fa 100644 --- a/jc/parsers/ufw_appinfo.py +++ b/jc/parsers/ufw_appinfo.py @@ -1,8 +1,12 @@ -"""jc - JSON CLI output utility `ufw app info [application]` command output parser +"""jc - JSON CLI output utility `ufw app info [application]` command +output parser -Supports individual apps via `ufw app info [application]` and all apps list via `ufw app info all`. +Supports individual apps via `ufw app info [application]` and all apps list +via `ufw app info all`. -Because `ufw` application definitions allow overlapping ports and port ranges, this parser preserves that behavior, but also provides `normalized` lists and ranges that remove duplicate ports and merge overlapping ranges. +Because `ufw` application definitions allow overlapping ports and port +ranges, this parser preserves that behavior, but also provides `normalized` +lists and ranges that remove duplicate ports and merge overlapping ranges. Usage (cli): @@ -43,31 +47,35 @@ Schema: ], "udp_ranges": [ { - "start": integer, # 'any' is converted to start/end: 0/65535 + "start": integer, # [0] "end": integer } ], "normalized_tcp_list": [ - integers # duplicates and overlapping are removed + integers # [1] ], "normalized_tcp_ranges": [ { - "start": integer, # 'any' is converted to start/end: 0/65535 - "end": integers # overlapping are merged + "start": integer, # [0] + "end": integers # [2] } ], "normalized_udp_list": [ - integers # duplicates and overlapping are removed + integers # [1] ], "normalized_udp_ranges": [ { - "start": integer, # 'any' is converted to start/end: 0/65535 - "end": integers # overlapping are merged + "start": integer, # [0] + "end": integers # [2] } ] } ] + [0] 'any' is converted to start/end: 0/65535 + [1] duplicates and overlapping are removed + [2] overlapping are merged + Examples: $ ufw app info MSN | jc --ufw-appinfo -p diff --git a/jc/parsers/uname.py b/jc/parsers/uname.py index 4c96d1c2..41fea719 100644 --- a/jc/parsers/uname.py +++ b/jc/parsers/uname.py @@ -57,8 +57,6 @@ class info(): description = '`uname -a` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'freebsd'] magic_commands = ['uname'] @@ -130,7 +128,7 @@ def parse(data, raw=False, quiet=False): fixup.insert(-1, 'unknown') fixup.insert(-1, 'unknown') data = ' '.join(fixup) - + parsed_line = data.split(maxsplit=3) if len(parsed_line) < 3: diff --git a/jc/parsers/universal.py b/jc/parsers/universal.py index c7137daf..a5a4df4e 100644 --- a/jc/parsers/universal.py +++ b/jc/parsers/universal.py @@ -13,16 +13,18 @@ def simple_table_parse(data): Parameters: - data: (list) Text data to parse that has been split into lines via .splitlines(). - Item 0 must be the header row. Any spaces in header names should be - changed to underscore '_'. You should also ensure headers are - lowercase by using .lower(). + data: (list) Text data to parse that has been split into lines + via .splitlines(). Item 0 must be the header row. + Any spaces in header names should be changed to + underscore '_'. You should also ensure headers are + lowercase by using .lower(). - Also, ensure there are no blank lines (list items) in the data. + Also, ensure there are no blank lines (list items) + in the data. Returns: - List of Dictionaries raw structured data + List of Dictionaries """ headers = [h for h in ' '.join(data[0].strip().split()).split() if h] raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), data[1:]) @@ -37,22 +39,26 @@ def sparse_table_parse(data, delim='\u2063'): Parameters: - data: (list) Text data to parse that has been split into lines via .splitlines(). - Item 0 must be the header row. Any spaces in header names should be - changed to underscore '_'. You should also ensure headers are - lowercase by using .lower(). Do not change the position of header - names as the positions are used to find the data. + data: (list) Text data to parse that has been split into lines + via .splitlines(). Item 0 must be the header row. + Any spaces in header names should be changed to + underscore '_'. You should also ensure headers are + lowercase by using .lower(). Do not change the + position of header names as the positions are used + to find the data. - Also, ensure there are no blank lines (list items) in the data. + Also, ensure there are no blank lines (list items) + in the data. - delim: (string) Delimiter to use. By default 'u\2063' (invisible separator) is used - since this is unlikely to ever be seen in terminal output. You can - change this for troubleshooting purposes or if there is a delimiter - conflict with your data. + delim: (string) Delimiter to use. By default 'u\2063' (invisible + separator) is used since this is unlikely to ever + be seen in terminal output. You can change this for + troubleshooting purposes or if there is a delimiter + conflict with your data. Returns: - List of Dictionaries raw structured data + List of Dictionaries """ output = [] header_text = data.pop(0) diff --git a/jc/parsers/upower.py b/jc/parsers/upower.py index 0d0480b8..8c5c1473 100644 --- a/jc/parsers/upower.py +++ b/jc/parsers/upower.py @@ -1,8 +1,10 @@ """jc - JSON CLI output utility `upower` command output parser -The `updated_epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `updated_epoch` calculated timestamp field is naive. (i.e. based on the +local time of the system the parser is run on) -The `updated_epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `updated_epoch_utc` calculated timestamp field is timezone-aware and is +only available if the timezone field is UTC. Usage (cli): @@ -31,8 +33,8 @@ Schema: "native_path": string, "power_supply": boolean, "updated": string, - "updated_epoch": integer, # null if date-time conversion fails - "updated_epoch_utc": integer, # null if date-time conversion fails + "updated_epoch": integer, # [0] + "updated_epoch_utc": integer, # [0] "updated_seconds_ago": integer, "has_history": boolean, "has_statistics": boolean, @@ -84,12 +86,14 @@ Schema: } ] + [0] null if date-time conversion fails + Examples: $ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p [ { - "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0", + "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/p...", "vendor": "NOTEBOOK", "model": "BAT", "serial": "0001", @@ -148,7 +152,7 @@ Examples: $ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p -r [ { - "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0", + "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/p...", "vendor": "NOTEBOOK", "model": "BAT", "serial": "0001", @@ -203,9 +207,6 @@ class info(): description = '`upower` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['upower'] @@ -238,7 +239,10 @@ def _process(proc_data): entry['updated_epoch_utc'] = ts.utc # top level boolean conversions - bool_list = ['power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed', 'lid_is_present'] + bool_list = [ + 'power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed', + 'lid_is_present' + ] for key in entry: if key in bool_list: entry[key] = jc.utils.convert_to_bool(entry[key]) @@ -374,7 +378,9 @@ def parse(data, raw=False, quiet=False): # general detail lines if line.startswith(' ') and ':' in line: - key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_').replace(' ', '_').replace('(', '').replace(')', '') + key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_')\ + .replace(' ', '_').replace('(', '')\ + .replace(')', '') val = line.split(':', maxsplit=1)[1].strip() device_obj['detail'][key] = val continue @@ -393,7 +399,9 @@ def parse(data, raw=False, quiet=False): # top level lines if line.startswith(' ') and ':' in line: - key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_').replace(' ', '_').replace('(', '').replace(')', '') + key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_')\ + .replace(' ', '_').replace('(', '')\ + .replace(')', '') val = line.split(':', maxsplit=1)[1].strip() device_obj[key] = val continue diff --git a/jc/parsers/uptime.py b/jc/parsers/uptime.py index 133a9d5e..88cada1b 100644 --- a/jc/parsers/uptime.py +++ b/jc/parsers/uptime.py @@ -74,8 +74,6 @@ class info(): description = '`uptime` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['uptime'] diff --git a/jc/parsers/vmstat.py b/jc/parsers/vmstat.py index bb0e6927..e33f4491 100644 --- a/jc/parsers/vmstat.py +++ b/jc/parsers/vmstat.py @@ -2,9 +2,11 @@ Options supported: `-a`, `-w`, `-d`, `-t` -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the timezone field is UTC. Usage (cli): @@ -60,11 +62,14 @@ Schema: "io_seconds": integer, "timestamp": string, "timezone": string, - "epoch": integer, # naive timestamp if -t flag is used - "epoch_utc": integer # aware timestamp if -t flag is used and UTC TZ + "epoch": integer, # [0] + "epoch_utc": integer # [1] } ] + [0] naive timestamp if -t flag is used + [1] aware timestamp if -t flag is used and UTC TZ + Examples: $ vmstat | jc --vmstat -p @@ -130,9 +135,6 @@ class info(): description = '`vmstat` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] magic_commands = ['vmstat'] @@ -153,11 +155,13 @@ def _process(proc_data): List of Dictionaries. Structured to conform to the schema. """ - int_list = ['runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', 'buffer_mem', - 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', 'blocks_out', - 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', 'io_wait_time', - 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', 'total_writes', - 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'] + int_list = [ + 'runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', + 'buffer_mem', 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', + 'blocks_out', 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', + 'io_wait_time', 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', + 'total_writes', 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds' + ] for entry in proc_data: for key in entry: diff --git a/jc/parsers/vmstat_s.py b/jc/parsers/vmstat_s.py index 6adbaf6d..f2b3a576 100644 --- a/jc/parsers/vmstat_s.py +++ b/jc/parsers/vmstat_s.py @@ -4,83 +4,100 @@ Options supported: `-a`, `-w`, `-d`, `-t` -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) -The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. +The `epoch_utc` calculated timestamp field is timezone-aware and is only +available if the timezone field is UTC. Usage (cli): $ vmstat | jc --vmstat-s -> Note: When piping `jc` converted `vmstat` output to other processes it may appear the output is hanging due to the OS pipe buffers. This is because `vmstat` output is too small to quickly fill up the buffer. Use the `-u` option to unbuffer the `jc` output if you would like immediate output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) for more information. +> Note: When piping `jc` converted `vmstat` output to other processes it may +appear the output is hanging due to the OS pipe buffers. This is because +`vmstat` output is too small to quickly fill up the buffer. Use the `-u` +option to unbuffer the `jc` output if you would like immediate output. See +the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) +for more information. Usage (module): import jc - result = jc.parse('vmstat_s', vmstat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parse('vmstat_s', vmstat_command_output.splitlines()) for item in result: # do something or import jc.parsers.vmstat_s - result = jc.parsers.vmstat_s.parse(vmstat_command_output.splitlines()) # result is an iterable object + # result is an iterable object (generator) + result = jc.parsers.vmstat_s.parse(vmstat_command_output.splitlines()) for item in result: # do something Schema: { - "runnable_procs": integer, - "uninterruptible_sleeping_procs": integer, - "virtual_mem_used": integer, - "free_mem": integer, - "buffer_mem": integer, - "cache_mem": integer, - "inactive_mem": integer, - "active_mem": integer, - "swap_in": integer, - "swap_out": integer, - "blocks_in": integer, - "blocks_out": integer, - "interrupts": integer, - "context_switches": integer, - "user_time": integer, - "system_time": integer, - "idle_time": integer, - "io_wait_time": integer, - "stolen_time": integer, - "disk": string, - "total_reads": integer, - "merged_reads": integer, - "sectors_read": integer, - "reading_ms": integer, - "total_writes": integer, - "merged_writes": integer, - "sectors_written": integer, - "writing_ms": integer, - "current_io": integer, - "io_seconds": integer, - "timestamp": string, - "timezone": string, - "epoch": integer, # naive timestamp if -t flag is used - "epoch_utc": integer # aware timestamp if -t flag is used and UTC TZ - "_jc_meta": # This object only exists if using -qq or ignore_exceptions=True + "runnable_procs": integer, + "uninterruptible_sleeping_procs": integer, + "virtual_mem_used": integer, + "free_mem": integer, + "buffer_mem": integer, + "cache_mem": integer, + "inactive_mem": integer, + "active_mem": integer, + "swap_in": integer, + "swap_out": integer, + "blocks_in": integer, + "blocks_out": integer, + "interrupts": integer, + "context_switches": integer, + "user_time": integer, + "system_time": integer, + "idle_time": integer, + "io_wait_time": integer, + "stolen_time": integer, + "disk": string, + "total_reads": integer, + "merged_reads": integer, + "sectors_read": integer, + "reading_ms": integer, + "total_writes": integer, + "merged_writes": integer, + "sectors_written": integer, + "writing_ms": integer, + "current_io": integer, + "io_seconds": integer, + "timestamp": string, + "timezone": string, + "epoch": integer, # [0] + "epoch_utc": integer # [1] + + # Below object only exists if using -qq or ignore_exceptions=True + + "_jc_meta": { - "success": boolean, # true if successfully parsed, false if error - "error": string, # exists if "success" is false - "line": string # exists if "success" is false + "success": boolean, # [2] + "error": string, # [3] + "line": string # [3] } } + [0] naive timestamp if -t flag is used + [1] aware timestamp if -t flag is used and UTC TZ + [2] false if error parsing + [3] exists if "success" is false + Examples: $ vmstat | jc --vmstat-s - {"runnable_procs":2,"uninterruptible_sleeping_procs":0,"virtual_mem_used":0,"free_mem":2794468,"buffer_mem":2108,"cache_mem":741208,"inactive_mem":null,"active_mem":null,"swap_in":0,"swap_out":0,"blocks_in":1,"blocks_out":3,"interrupts":29,"context_switches":57,"user_time":0,"system_time":0,"idle_time":99,"io_wait_time":0,"stolen_time":0,"timestamp":null,"timezone":null} + {"runnable_procs":2,"uninterruptible_sleeping_procs":0,"virtual_mem...} ... $ vmstat | jc --vmstat-s -r - {"runnable_procs":"2","uninterruptible_sleeping_procs":"0","virtual_mem_used":"0","free_mem":"2794468","buffer_mem":"2108","cache_mem":"741208","inactive_mem":null,"active_mem":null,"swap_in":"0","swap_out":"0","blocks_in":"1","blocks_out":"3","interrupts":"29","context_switches":"57","user_time":"0","system_time":"0","idle_time":"99","io_wait_time":"0","stolen_time":"0","timestamp":null,"timezone":null} + {"runnable_procs":"2","uninterruptible_sleeping_procs":"0","virtua...} ... """ import jc.utils @@ -94,8 +111,6 @@ class info(): description = '`vmstat` command streaming parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux'] streaming = True @@ -115,11 +130,13 @@ def _process(proc_data): Dictionary. Structured data to conform to the schema. """ - int_list = ['runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', 'buffer_mem', - 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', 'blocks_out', - 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', 'io_wait_time', - 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', 'total_writes', - 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'] + int_list = [ + 'runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', + 'buffer_mem', 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', + 'blocks_out', 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', + 'io_wait_time', 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', + 'total_writes', 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds' + ] for key in proc_data: if key in int_list: @@ -139,7 +156,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False): Parameters: - data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) + data: (iterable) line-based text data to parse + (e.g. sys.stdin or str.splitlines()) + raw: (boolean) output preprocessed JSON if True quiet: (boolean) suppress warning messages if True ignore_exceptions: (boolean) ignore parsing exceptions if True diff --git a/jc/parsers/w.py b/jc/parsers/w.py index 185cfbda..334b98dc 100644 --- a/jc/parsers/w.py +++ b/jc/parsers/w.py @@ -113,8 +113,6 @@ class info(): description = '`w` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['w'] diff --git a/jc/parsers/wc.py b/jc/parsers/wc.py index a8492263..64eee561 100644 --- a/jc/parsers/wc.py +++ b/jc/parsers/wc.py @@ -63,8 +63,6 @@ class info(): description = '`wc` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['wc'] diff --git a/jc/parsers/who.py b/jc/parsers/who.py index 6fa6dc0c..f7329fbe 100644 --- a/jc/parsers/who.py +++ b/jc/parsers/who.py @@ -2,7 +2,8 @@ Accepts any of the following who options (or no options): `-aTH` -The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) +The `epoch` calculated timestamp field is naive. (i.e. based on the local +time of the system the parser is run on) Usage (cli): @@ -31,7 +32,7 @@ Schema: "writeable_tty": string, "tty": string, "time": string, - "epoch": integer, # naive timestamp. null if time cannot be converted + "epoch": integer, # [0] "idle": string, "pid": integer, "from": string, @@ -39,6 +40,8 @@ Schema: } ] + [0] naive timestamp. null if time cannot be converted + Examples: $ who -a | jc --who -p @@ -142,9 +145,6 @@ class info(): description = '`who` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' - # details = 'enter any other details here' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] magic_commands = ['who'] diff --git a/jc/parsers/xml.py b/jc/parsers/xml.py index ef7674d1..07038ade 100644 --- a/jc/parsers/xml.py +++ b/jc/parsers/xml.py @@ -81,8 +81,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using the xmltodict library at https://github.com/martinblech/xmltodict' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] diff --git a/jc/parsers/yaml.py b/jc/parsers/yaml.py index e19a8c5f..c5a2bbf0 100644 --- a/jc/parsers/yaml.py +++ b/jc/parsers/yaml.py @@ -95,8 +95,6 @@ class info(): author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' details = 'Using the ruamel.yaml library at https://pypi.org/project/ruamel.yaml' - - # compatible options: linux, darwin, cygwin, win32, aix, freebsd compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']