From 246c707c98d3128b4e38f5c4b23a1e0ceedc0b0c Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 18 Apr 2021 11:46:42 -0700 Subject: [PATCH] use jc.utils conversions --- CHANGELOG | 1 + docs/parsers/acpi.md | 2 +- docs/parsers/airport.md | 2 +- docs/parsers/airport_s.md | 2 +- docs/parsers/blkid.md | 2 +- docs/parsers/cksum.md | 2 +- docs/parsers/df.md | 2 +- docs/parsers/dir.md | 2 +- docs/parsers/dmidecode.md | 2 +- docs/parsers/du.md | 2 +- docs/parsers/free.md | 2 +- docs/parsers/fstab.md | 2 +- docs/parsers/group.md | 2 +- docs/parsers/hash.md | 2 +- docs/parsers/hciconfig.md | 2 +- docs/parsers/history.md | 2 +- docs/parsers/id.md | 2 +- docs/parsers/ifconfig.md | 2 +- docs/utils.md | 48 +++++++++++++++++++ jc/parsers/acpi.py | 22 ++------- jc/parsers/airport.py | 7 +-- jc/parsers/airport_s.py | 12 ++--- jc/parsers/arp.py | 5 +- jc/parsers/blkid.py | 7 +-- jc/parsers/cksum.py | 8 ++-- jc/parsers/df.py | 14 ++---- jc/parsers/dig.py | 50 ++++---------------- jc/parsers/dir.py | 11 ++--- jc/parsers/dmidecode.py | 8 +--- jc/parsers/du.py | 8 +--- jc/parsers/foo.py | 2 + jc/parsers/free.py | 8 +--- jc/parsers/fstab.py | 8 +--- jc/parsers/group.py | 8 +--- jc/parsers/hash.py | 9 +--- jc/parsers/hciconfig.py | 8 +--- jc/parsers/history.py | 6 +-- jc/parsers/id.py | 17 ++----- jc/parsers/ifconfig.py | 11 ++--- jc/utils.py | 62 ++++++++++++++++++++++++- tests/fixtures/centos-7.7/df-h.json | 2 +- tests/fixtures/centos-7.7/free-h.json | 2 +- tests/fixtures/osx-10.11.6/df-h.json | 2 +- tests/fixtures/osx-10.14.6/df-h.json | 2 +- tests/fixtures/ubuntu-18.04/df-h.json | 2 +- tests/fixtures/ubuntu-18.04/free-h.json | 2 +- 46 files changed, 190 insertions(+), 196 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e02a1c39..7fbf50c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ jc changelog - Update dig parser to add support for Additional Section and Opt Pseudosection - Update dig parser to add query_size field - Use dig parser as the main example in readme, documentation, and man page +- Standardize int, float, and boolean conversion rules 20210413 v1.15.1 - New feature to show parser documentation interactively with -h --parser_name diff --git a/docs/parsers/acpi.md b/docs/parsers/acpi.md index 3df64cd5..cac7087c 100644 --- a/docs/parsers/acpi.md +++ b/docs/parsers/acpi.md @@ -252,4 +252,4 @@ Returns: ## Parser Information Compatibility: linux -Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/airport.md b/docs/parsers/airport.md index 93a05dcd..9966499c 100644 --- a/docs/parsers/airport.md +++ b/docs/parsers/airport.md @@ -105,4 +105,4 @@ Returns: ## Parser Information Compatibility: darwin -Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/airport_s.md b/docs/parsers/airport_s.md index 7ce6792d..08929c09 100644 --- a/docs/parsers/airport_s.md +++ b/docs/parsers/airport_s.md @@ -133,4 +133,4 @@ Returns: ## Parser Information Compatibility: darwin -Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/blkid.md b/docs/parsers/blkid.md index a8738fbb..f3246fb1 100644 --- a/docs/parsers/blkid.md +++ b/docs/parsers/blkid.md @@ -145,4 +145,4 @@ Returns: ## Parser Information Compatibility: linux -Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/cksum.md b/docs/parsers/cksum.md index f5b56c59..21c8c175 100644 --- a/docs/parsers/cksum.md +++ b/docs/parsers/cksum.md @@ -79,4 +79,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, cygwin, aix, freebsd -Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/df.md b/docs/parsers/df.md index 7eb225f6..2bed3ed4 100644 --- a/docs/parsers/df.md +++ b/docs/parsers/df.md @@ -122,4 +122,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, freebsd -Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/dir.md b/docs/parsers/dir.md index f3607377..de4d2aad 100644 --- a/docs/parsers/dir.md +++ b/docs/parsers/dir.md @@ -145,4 +145,4 @@ Returns: ## Parser Information Compatibility: win32 -Version 1.1 by Rasheed Elsaleh (rasheed@rebelliondefense.com) +Version 1.2 by Rasheed Elsaleh (rasheed@rebelliondefense.com) diff --git a/docs/parsers/dmidecode.md b/docs/parsers/dmidecode.md index 62d2a7a6..7f85b819 100644 --- a/docs/parsers/dmidecode.md +++ b/docs/parsers/dmidecode.md @@ -150,4 +150,4 @@ Returns: ## Parser Information Compatibility: linux -Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/du.md b/docs/parsers/du.md index 96b067f4..9d87abbb 100644 --- a/docs/parsers/du.md +++ b/docs/parsers/du.md @@ -112,4 +112,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, aix, freebsd -Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/free.md b/docs/parsers/free.md index 13f5f662..34736377 100644 --- a/docs/parsers/free.md +++ b/docs/parsers/free.md @@ -97,4 +97,4 @@ Returns: ## Parser Information Compatibility: linux -Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/fstab.md b/docs/parsers/fstab.md index 396eefff..a6ab9d22 100644 --- a/docs/parsers/fstab.md +++ b/docs/parsers/fstab.md @@ -110,4 +110,4 @@ Returns: ## Parser Information Compatibility: linux, freebsd -Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/group.md b/docs/parsers/group.md index a9eb2204..034c80d6 100644 --- a/docs/parsers/group.md +++ b/docs/parsers/group.md @@ -134,4 +134,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, aix, freebsd -Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/hash.md b/docs/parsers/hash.md index 99ace38f..721e8b83 100644 --- a/docs/parsers/hash.md +++ b/docs/parsers/hash.md @@ -62,4 +62,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, cygwin, aix, freebsd -Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/hciconfig.md b/docs/parsers/hciconfig.md index 6e6f84a1..93e34812 100644 --- a/docs/parsers/hciconfig.md +++ b/docs/parsers/hciconfig.md @@ -342,4 +342,4 @@ Returns: ## Parser Information Compatibility: linux -Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/history.md b/docs/parsers/history.md index b2a4ae2d..81716d62 100644 --- a/docs/parsers/history.md +++ b/docs/parsers/history.md @@ -83,4 +83,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, cygwin, aix, freebsd -Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/id.md b/docs/parsers/id.md index d44dd7a4..303858f1 100644 --- a/docs/parsers/id.md +++ b/docs/parsers/id.md @@ -130,4 +130,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, aix, freebsd -Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/ifconfig.md b/docs/parsers/ifconfig.md index ef58b50f..985be4be 100644 --- a/docs/parsers/ifconfig.md +++ b/docs/parsers/ifconfig.md @@ -211,4 +211,4 @@ Returns: ## Parser Information Compatibility: linux, aix, freebsd, darwin -Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/utils.md b/docs/utils.md index 077f969c..60bd45cc 100644 --- a/docs/utils.md +++ b/docs/utils.md @@ -69,6 +69,54 @@ Returns: Boolean True if input string (data) contains non-whitespace characters, otherwise False +## convert_to_int +```python +convert_to_int(value) +``` + +Converts string input to integer by stripping all non-numeric characters + +Parameters: + + value: (string) Input value + +Returns: + + integer/None Integer if successful conversion, otherwise None + + +## convert_to_float +```python +convert_to_float(value) +``` + +Converts string input to float by stripping all non-numeric characters + +Parameters: + + value: (string) Input value + +Returns: + + float/None Float if successful conversion, otherwise None + + +## convert_to_bool +```python +convert_to_bool(value) +``` + +Converts string, integer, or float input to boolean by checking for 'truthy' values + +Parameters: + + value: (string/integer/float) Input value + +Returns: + + True/False False unless a 'truthy' number or string is found ('y', 'yes', 'true', '1', 1, -1, etc.) + + ## timestamp ```python timestamp(datetime_string) diff --git a/jc/parsers/acpi.py b/jc/parsers/acpi.py index 6937d59b..59d09191 100644 --- a/jc/parsers/acpi.py +++ b/jc/parsers/acpi.py @@ -227,7 +227,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`acpi` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -258,36 +258,24 @@ def _process(proc_data): for entry in proc_data: for key in int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) if 'trip_points' in entry: for tp in entry['trip_points']: for key in int_list: if key in tp: - try: - tp[key] = int(tp[key]) - except (ValueError): - tp[key] = None + tp[key] = jc.utils.convert_to_int(tp[key]) for entry in proc_data: for key in float_list: if key in entry: - try: - entry[key] = float(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_float(entry[key]) if 'trip_points' in entry: for tp in entry['trip_points']: for key in float_list: if key in tp: - try: - tp[key] = float(tp[key]) - except (ValueError): - tp[key] = None + tp[key] = jc.utils.convert_to_float(tp[key]) for entry in proc_data: if 'until_charged' in entry: diff --git a/jc/parsers/airport.py b/jc/parsers/airport.py index 546989e7..f541316d 100644 --- a/jc/parsers/airport.py +++ b/jc/parsers/airport.py @@ -80,7 +80,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.2' + version = '1.3' description = '`airport -I` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -111,10 +111,7 @@ def _process(proc_data): 'lasttxrate', 'maxrate', 'lastassocstatus', 'mcs'] for key in proc_data: if key in int_list: - try: - proc_data[key] = int(proc_data[key]) - except (ValueError): - proc_data[key] = None + proc_data[key] = jc.utils.convert_to_int(proc_data[key]) return proc_data diff --git a/jc/parsers/airport_s.py b/jc/parsers/airport_s.py index 4158f398..3ae4aef9 100644 --- a/jc/parsers/airport_s.py +++ b/jc/parsers/airport_s.py @@ -109,7 +109,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = '`airport -s` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -141,19 +141,13 @@ def _process(proc_data): int_list = ['rssi'] for key in int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) # booleans bool_list = ['ht'] for key in entry: if key in bool_list: - try: - entry[key] = True if entry[key] == 'Y' else False - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_bool(entry[key]) if 'security' in entry: entry['security'] = entry['security'].split() diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 4df2f744..896e37c4 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -152,10 +152,7 @@ def _process(proc_data): int_list = ['expires'] for key in int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/blkid.py b/jc/parsers/blkid.py index 4acb1cb9..0153efc7 100644 --- a/jc/parsers/blkid.py +++ b/jc/parsers/blkid.py @@ -121,7 +121,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = '`blkid` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -157,10 +157,7 @@ def _process(proc_data): 'id_iolimit_logical_sector_size'] for key in int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/cksum.py b/jc/parsers/cksum.py index 32a6c24d..b3150f6e 100644 --- a/jc/parsers/cksum.py +++ b/jc/parsers/cksum.py @@ -54,7 +54,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`cksum` and `sum` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -84,10 +84,8 @@ def _process(proc_data): int_list = ['checksum', 'blocks'] for key in int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) + return proc_data diff --git a/jc/parsers/df.py b/jc/parsers/df.py index 5fd8c3bb..714c4ae4 100644 --- a/jc/parsers/df.py +++ b/jc/parsers/df.py @@ -98,7 +98,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.6' + version = '1.7' description = '`df` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -144,11 +144,7 @@ def _process(proc_data): # change any entry for key with '_blocks' in the name to int for k in entry: if '_blocks' in str(k): - try: - blocks_int = int(entry[k]) - entry[k] = blocks_int - except (ValueError): - entry[k] = None + entry[k] = jc.utils.convert_to_int(entry[k]) # remove percent sign from 'use_percent', 'capacity_percent', and 'iused_percent' if 'use_percent' in entry: @@ -164,11 +160,7 @@ def _process(proc_data): int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree', 'iused', 'iused_percent'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/dig.py b/jc/parsers/dig.py index 8bbb621c..4ceccfea 100644 --- a/jc/parsers/dig.py +++ b/jc/parsers/dig.py @@ -302,67 +302,35 @@ 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'] + int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', 'rcvd', + 'query_size', 'query_time'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) if 'axfr' in entry: for ax in entry['axfr']: - try: - ttl_int = int(ax['ttl']) - ax['ttl'] = ttl_int - except (ValueError): - ax['ttl'] = None + ax['ttl'] = jc.utils.convert_to_int(ax['ttl']) if 'opt_pseudosection' in entry: if 'edns' in entry['opt_pseudosection']: if 'version' in entry['opt_pseudosection']['edns']: - try: - entry['opt_pseudosection']['edns']['version'] = int(entry['opt_pseudosection']['edns']['version']) - except (ValueError): - entry['opt_pseudosection']['edns']['version'] = None + entry['opt_pseudosection']['edns']['version'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version']) if 'udp' in entry['opt_pseudosection']['edns']: - try: - entry['opt_pseudosection']['edns']['udp'] = int(entry['opt_pseudosection']['edns']['udp']) - except (ValueError): - entry['opt_pseudosection']['edns']['udp'] = None + entry['opt_pseudosection']['edns']['udp'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp']) if 'answer' in entry: for ans in entry['answer']: - try: - ttl_int = int(ans['ttl']) - ans['ttl'] = ttl_int - except (ValueError): - ans['ttl'] = None + ans['ttl'] = jc.utils.convert_to_int(ans['ttl']) if 'additional' in entry: for add in entry['additional']: - try: - ttl_int = int(add['ttl']) - add['ttl'] = ttl_int - except (ValueError): - add['ttl'] = None + add['ttl'] = jc.utils.convert_to_int(add['ttl']) if 'authority' in entry: for auth in entry['authority']: - try: - ttl_int = int(auth['ttl']) - auth['ttl'] = ttl_int - except (ValueError): - auth['ttl'] = None - - if 'query_time' in entry: - try: - qt_int = int(entry['query_time'].split()[0]) - entry['query_time'] = qt_int - except (ValueError): - entry['query_time'] = None + auth['ttl'] = jc.utils.convert_to_int(auth['ttl']) if 'when' in entry: ts = jc.utils.timestamp(entry['when']) diff --git a/jc/parsers/dir.py b/jc/parsers/dir.py index dac056b4..19fae60a 100644 --- a/jc/parsers/dir.py +++ b/jc/parsers/dir.py @@ -121,7 +121,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`dir` command parser' author = 'Rasheed Elsaleh' author_email = 'rasheed@rebelliondefense.com' @@ -156,13 +156,8 @@ def _process(proc_data): # add ints int_list = ["size"] for key in int_list: - if entry.get(key): - try: - key_int = int(entry[key].replace(",", "")) - except ValueError: - entry[key] = None - else: - entry[key] = key_int + if key in entry: + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/dmidecode.py b/jc/parsers/dmidecode.py index fc2c1747..5c7e6971 100644 --- a/jc/parsers/dmidecode.py +++ b/jc/parsers/dmidecode.py @@ -125,7 +125,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.2' + version = '1.3' description = '`dmidecode` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -155,11 +155,7 @@ def _process(proc_data): int_list = ['type', 'bytes'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) if not entry['values']: entry['values'] = None diff --git a/jc/parsers/du.py b/jc/parsers/du.py index 553596a1..d5dd592e 100644 --- a/jc/parsers/du.py +++ b/jc/parsers/du.py @@ -88,7 +88,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = '`du` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -118,11 +118,7 @@ def _process(proc_data): for entry in proc_data: for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/foo.py b/jc/parsers/foo.py index 25d2c98a..ca3e828d 100644 --- a/jc/parsers/foo.py +++ b/jc/parsers/foo.py @@ -66,6 +66,8 @@ def _process(proc_data): """ # rebuild output for added semantic information + # use helper functions in jc.utils for int, float, bool conversions and timestamps + return proc_data diff --git a/jc/parsers/free.py b/jc/parsers/free.py index 09d2bdb7..c8fcc116 100644 --- a/jc/parsers/free.py +++ b/jc/parsers/free.py @@ -73,7 +73,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = '`free` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -103,11 +103,7 @@ def _process(proc_data): int_list = ['total', 'used', 'free', 'shared', 'buff_cache', 'available'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/fstab.py b/jc/parsers/fstab.py index 5892a748..4620a4f6 100644 --- a/jc/parsers/fstab.py +++ b/jc/parsers/fstab.py @@ -85,7 +85,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = '`/etc/fstab` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -113,11 +113,7 @@ def _process(proc_data): int_list = ['fs_freq', 'fs_passno'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/group.py b/jc/parsers/group.py index eb2de469..22ba0e66 100644 --- a/jc/parsers/group.py +++ b/jc/parsers/group.py @@ -109,7 +109,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.2' + version = '1.3' description = '`/etc/group` file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -138,11 +138,7 @@ def _process(proc_data): int_list = ['gid'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) if entry['members'] == ['']: entry['members'] = [] diff --git a/jc/parsers/hash.py b/jc/parsers/hash.py index 54b4546c..f73ac0fa 100644 --- a/jc/parsers/hash.py +++ b/jc/parsers/hash.py @@ -38,7 +38,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`hash` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -63,15 +63,10 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ for entry in proc_data: - # change to int int_list = ['hits'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data diff --git a/jc/parsers/hciconfig.py b/jc/parsers/hciconfig.py index e1f1ba9c..27801b38 100644 --- a/jc/parsers/hciconfig.py +++ b/jc/parsers/hciconfig.py @@ -317,7 +317,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`hciconfig` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -346,15 +346,11 @@ def _process(proc_data): for entry in proc_data: - # integers 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 int_list: if key in entry: - try: - entry[key] = int(entry[key]) - except (ValueError): - entry[key] = None + 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']: entry['service_classes'] = None diff --git a/jc/parsers/history.py b/jc/parsers/history.py index f5fd77ba..24f9851d 100644 --- a/jc/parsers/history.py +++ b/jc/parsers/history.py @@ -57,7 +57,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = '`history` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -82,12 +82,10 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ - - # rebuild output for added semantic information processed = [] for k, v in proc_data.items(): proc_line = { - 'line': int(k) if k.isdigit() else None, + 'line': jc.utils.convert_to_int(k), 'command': v, } processed.append(proc_line) diff --git a/jc/parsers/id.py b/jc/parsers/id.py index c603f3cc..c3f54e44 100644 --- a/jc/parsers/id.py +++ b/jc/parsers/id.py @@ -105,7 +105,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.2' + version = '1.3' description = '`id` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -133,25 +133,16 @@ def _process(proc_data): """ if 'uid' in proc_data: if 'id' in proc_data['uid']: - try: - proc_data['uid']['id'] = int(proc_data['uid']['id']) - except (ValueError): - proc_data['uid']['id'] = None + proc_data['uid']['id'] = jc.utils.convert_to_int(proc_data['uid']['id']) if 'gid' in proc_data: if 'id' in proc_data['gid']: - try: - proc_data['gid']['id'] = int(proc_data['gid']['id']) - except (ValueError): - proc_data['gid']['id'] = None + proc_data['gid']['id'] = jc.utils.convert_to_int(proc_data['gid']['id']) if 'groups' in proc_data: for group in proc_data['groups']: if 'id' in group: - try: - group['id'] = int(group['id']) - except (ValueError): - group['id'] = None + group['id'] = jc.utils.convert_to_int(group['id']) return proc_data diff --git a/jc/parsers/ifconfig.py b/jc/parsers/ifconfig.py index 9be8d806..c45b60fb 100644 --- a/jc/parsers/ifconfig.py +++ b/jc/parsers/ifconfig.py @@ -188,7 +188,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.9' + version = '1.10' description = '`ifconfig` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -398,7 +398,8 @@ class _IfconfigParser(object): if match: details = match.groupdict() for k, v in details.items(): - if isinstance(v, str): details[k] = v.strip() + if isinstance(v, str): + details[k] = v.strip() _interface.update(details) if _interface is not None: available_interfaces[_interface['name']] = self.update_interface_details(_interface) @@ -435,11 +436,7 @@ def _process(proc_data): 'tx_collisions', 'metric'] for key in int_list: if key in entry: - try: - key_int = int(entry[key]) - entry[key] = key_int - except (ValueError, TypeError): - entry[key] = None + entry[key] = jc.utils.convert_to_int(entry[key]) # convert OSX-style subnet mask to dotted quad if 'ipv4_mask' in entry: diff --git a/jc/utils.py b/jc/utils.py index 186592f7..278b2664 100644 --- a/jc/utils.py +++ b/jc/utils.py @@ -92,16 +92,76 @@ def convert_to_int(value): value: (string) Input value Returns: + integer/None Integer if successful conversion, otherwise None """ try: - value = int(re.sub('[^0-9]', '', value)) + value = int(re.sub(r'[^0-9\-\.]', '', value)) + except (ValueError, TypeError): + try: + value = round(convert_to_float(value)) + except (ValueError, TypeError): + return None + + return value + + +def convert_to_float(value): + """ + Converts string input to float by stripping all non-numeric characters + + Parameters: + + value: (string) Input value + + Returns: + + float/None Float if successful conversion, otherwise None + """ + try: + value = float(re.sub(r'[^0-9\-\.]', '', value)) except (ValueError, TypeError): return None return value +def convert_to_bool(value): + """ + Converts string, integer, or float input to boolean by checking for 'truthy' values + + Parameters: + + value: (string/integer/float) Input value + + Returns: + + True/False False unless a 'truthy' number or string is found ('y', 'yes', 'true', '1', 1, -1, etc.) + """ + # if number, then bool it + # if string, try to convert to float + # if float converts, then bool the result + # if float does not convert then look for truthy string and bool True + # else False + truthy = ['y', 'yes', 'true'] + + if isinstance(value, (int, float)): + return bool(value) + + if isinstance(value, str): + try: + test_value = convert_to_float(value) + if test_value is not None: + return bool(test_value) + except Exception: + pass + + if value: + return True if value.lower() in truthy else False + + return False + + class timestamp: """ Input a date-time text string of several formats and convert to a naive or timezone-aware epoch timestamp in UTC diff --git a/tests/fixtures/centos-7.7/df-h.json b/tests/fixtures/centos-7.7/df-h.json index f1e3f13b..13569fd6 100644 --- a/tests/fixtures/centos-7.7/df-h.json +++ b/tests/fixtures/centos-7.7/df-h.json @@ -1 +1 @@ -[{"filesystem": "devtmpfs", "size": "1.9G", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/dev"}, {"filesystem": "tmpfs", "size": "1.9G", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/dev/shm"}, {"filesystem": "tmpfs", "size": "1.9G", "used": null, "available": null, "use_percent": 1, "mounted_on": "/run"}, {"filesystem": "tmpfs", "size": "1.9G", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/sys/fs/cgroup"}, {"filesystem": "/dev/mapper/centos-root", "size": "17G", "used": null, "available": null, "use_percent": 11, "mounted_on": "/"}, {"filesystem": "/dev/sda1", "size": "1014M", "used": null, "available": null, "use_percent": 23, "mounted_on": "/boot"}, {"filesystem": "tmpfs", "size": "378M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/run/user/1000"}] +[{"filesystem":"devtmpfs","size":"1.9G","used":0,"mounted_on":"/dev","available":2,"use_percent":0},{"filesystem":"tmpfs","size":"1.9G","used":0,"mounted_on":"/dev/shm","available":2,"use_percent":0},{"filesystem":"tmpfs","size":"1.9G","used":12,"mounted_on":"/run","available":2,"use_percent":1},{"filesystem":"tmpfs","size":"1.9G","used":0,"mounted_on":"/sys/fs/cgroup","available":2,"use_percent":0},{"filesystem":"/dev/mapper/centos-root","size":"17G","used":2,"mounted_on":"/","available":16,"use_percent":11},{"filesystem":"/dev/sda1","size":"1014M","used":233,"mounted_on":"/boot","available":782,"use_percent":23},{"filesystem":"tmpfs","size":"378M","used":0,"mounted_on":"/run/user/1000","available":378,"use_percent":0}] diff --git a/tests/fixtures/centos-7.7/free-h.json b/tests/fixtures/centos-7.7/free-h.json index 4bc5380a..1d47988f 100644 --- a/tests/fixtures/centos-7.7/free-h.json +++ b/tests/fixtures/centos-7.7/free-h.json @@ -1 +1 @@ -[{"type": "Mem", "total": null, "used": null, "free": null, "shared": null, "buff_cache": null, "available": null}, {"type": "Swap", "total": null, "used": null, "free": null}] +[{"type":"Mem","total":4,"used":217,"free":3,"shared":11,"buff_cache":267,"available":3},{"type":"Swap","total":2,"used":0,"free":2}] diff --git a/tests/fixtures/osx-10.11.6/df-h.json b/tests/fixtures/osx-10.11.6/df-h.json index 078f486b..b69a0c51 100644 --- a/tests/fixtures/osx-10.11.6/df-h.json +++ b/tests/fixtures/osx-10.11.6/df-h.json @@ -1 +1 @@ -[{"filesystem": "/dev/disk1s1", "size": "466Gi", "used": null, "iused": 674413, "ifree": 9223372036854101394, "mounted_on": "/", "available": null, "capacity_percent": 30, "iused_percent": 0}, {"filesystem": "devfs", "size": "188Ki", "used": null, "iused": 650, "ifree": 0, "mounted_on": "/dev", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "/dev/disk1s4", "size": "466Gi", "used": null, "iused": 2, "ifree": 9223372036854775805, "mounted_on": "/private/var/vm", "available": null, "capacity_percent": 1, "iused_percent": 0}, {"filesystem": "map -hosts", "size": "0Bi", "used": null, "iused": 0, "ifree": 0, "mounted_on": "/net", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "map auto_home", "size": "0Bi", "used": null, "iused": 0, "ifree": 0, "mounted_on": "/home", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "//brazil@MyCloudEX2Ultra._afpovertcp._tcp.local/brazil", "size": "3.5Ti", "used": null, "iused": 301134832, "ifree": 649465741, "mounted_on": "/Volumes/brazil", "available": null, "capacity_percent": 32, "iused_percent": 32}] +[{"filesystem":"/dev/disk1s1","size":"466Gi","used":137,"iused":674413,"ifree":9223372036854101394,"mounted_on":"/","available":326,"capacity_percent":30,"iused_percent":0},{"filesystem":"devfs","size":"188Ki","used":188,"iused":650,"ifree":0,"mounted_on":"/dev","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"/dev/disk1s4","size":"466Gi","used":2,"iused":2,"ifree":9223372036854775805,"mounted_on":"/private/var/vm","available":326,"capacity_percent":1,"iused_percent":0},{"filesystem":"map -hosts","size":"0Bi","used":0,"iused":0,"ifree":0,"mounted_on":"/net","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"map auto_home","size":"0Bi","used":0,"iused":0,"ifree":0,"mounted_on":"/home","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"//brazil@MyCloudEX2Ultra._afpovertcp._tcp.local/brazil","size":"3.5Ti","used":1,"iused":301134832,"ifree":649465741,"mounted_on":"/Volumes/brazil","available":2,"capacity_percent":32,"iused_percent":32}] diff --git a/tests/fixtures/osx-10.14.6/df-h.json b/tests/fixtures/osx-10.14.6/df-h.json index ca49a8b8..4467cf76 100644 --- a/tests/fixtures/osx-10.14.6/df-h.json +++ b/tests/fixtures/osx-10.14.6/df-h.json @@ -1 +1 @@ -[{"filesystem": "/dev/disk1s1", "size": "466Gi", "used": null, "iused": 1507697, "ifree": 9223372036853268110, "mounted_on": "/", "available": null, "capacity_percent": 32, "iused_percent": 0}, {"filesystem": "devfs", "size": "334Ki", "used": null, "iused": 1154, "ifree": 0, "mounted_on": "/dev", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "/dev/disk1s4", "size": "466Gi", "used": null, "iused": 6, "ifree": 9223372036854775801, "mounted_on": "/private/var/vm", "available": null, "capacity_percent": 2, "iused_percent": 0}, {"filesystem": "map -hosts", "size": "0Bi", "used": null, "iused": 0, "ifree": 0, "mounted_on": "/net", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "map auto_home", "size": "0Bi", "used": null, "iused": 0, "ifree": 0, "mounted_on": "/home", "available": null, "capacity_percent": 100, "iused_percent": 100}, {"filesystem": "/dev/disk2s2", "size": "6.9Gi", "used": null, "iused": 8, "ifree": 4294967271, "mounted_on": "/Volumes/InstallESD", "available": null, "capacity_percent": 76, "iused_percent": 0}, {"filesystem": "com.apple.TimeMachine.2019-11-29-075900@/dev/disk1s1", "size": "466Gi", "used": null, "iused": 1459164, "ifree": 9223372036853316643, "mounted_on": "/Volumes/com.apple.TimeMachine.localsnapshots/Backups.backupdb/kbrazil-mac/2019-11-29-075900/Macintosh HD", "available": null, "capacity_percent": 30, "iused_percent": 0}, {"filesystem": "//brazil@MyCloudEX2Ultra._afpovertcp._tcp.local/brazil", "size": "3.5Ti", "used": null, "iused": 301134832, "ifree": 649465741, "mounted_on": "/Volumes/brazil", "available": null, "capacity_percent": 32, "iused_percent": 32}] +[{"filesystem":"/dev/disk1s1","size":"466Gi","used":144,"iused":1507697,"ifree":9223372036853268110,"mounted_on":"/","available":315,"capacity_percent":32,"iused_percent":0},{"filesystem":"devfs","size":"334Ki","used":334,"iused":1154,"ifree":0,"mounted_on":"/dev","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"/dev/disk1s4","size":"466Gi","used":6,"iused":6,"ifree":9223372036854775801,"mounted_on":"/private/var/vm","available":315,"capacity_percent":2,"iused_percent":0},{"filesystem":"map -hosts","size":"0Bi","used":0,"iused":0,"ifree":0,"mounted_on":"/net","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"map auto_home","size":"0Bi","used":0,"iused":0,"ifree":0,"mounted_on":"/home","available":0,"capacity_percent":100,"iused_percent":100},{"filesystem":"/dev/disk2s2","size":"6.9Gi","used":5,"iused":8,"ifree":4294967271,"mounted_on":"/Volumes/InstallESD","available":2,"capacity_percent":76,"iused_percent":0},{"filesystem":"com.apple.TimeMachine.2019-11-29-075900@/dev/disk1s1","size":"466Gi","used":132,"iused":1459164,"ifree":9223372036853316643,"mounted_on":"/Volumes/com.apple.TimeMachine.localsnapshots/Backups.backupdb/kbrazil-mac/2019-11-29-075900/Macintosh HD","available":315,"capacity_percent":30,"iused_percent":0},{"filesystem":"//brazil@MyCloudEX2Ultra._afpovertcp._tcp.local/brazil","size":"3.5Ti","used":1,"iused":301134832,"ifree":649465741,"mounted_on":"/Volumes/brazil","available":2,"capacity_percent":32,"iused_percent":32}] diff --git a/tests/fixtures/ubuntu-18.04/df-h.json b/tests/fixtures/ubuntu-18.04/df-h.json index 56d3a3d8..90617838 100644 --- a/tests/fixtures/ubuntu-18.04/df-h.json +++ b/tests/fixtures/ubuntu-18.04/df-h.json @@ -1 +1 @@ -[{"filesystem": "udev", "size": "955M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/dev"}, {"filesystem": "tmpfs", "size": "198M", "used": null, "available": null, "use_percent": 1, "mounted_on": "/run"}, {"filesystem": "/dev/sda2", "size": "20G", "used": null, "available": null, "use_percent": 30, "mounted_on": "/"}, {"filesystem": "tmpfs", "size": "986M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/dev/shm"}, {"filesystem": "tmpfs", "size": "5.0M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/run/lock"}, {"filesystem": "tmpfs", "size": "986M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/sys/fs/cgroup"}, {"filesystem": "/dev/loop0", "size": "55M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/core18/1223"}, {"filesystem": "/dev/loop1", "size": "11M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/slcli/383"}, {"filesystem": "/dev/loop2", "size": "89M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/core/7396"}, {"filesystem": "/dev/loop3", "size": "67M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/google-cloud-sdk/103"}, {"filesystem": "/dev/loop5", "size": "55M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/core18/1074"}, {"filesystem": "/dev/loop7", "size": "8.7M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/doctl/187"}, {"filesystem": "/dev/loop8", "size": "3.2M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/stress-ng/847"}, {"filesystem": "/dev/loop10", "size": "90M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/core/7917"}, {"filesystem": "/dev/loop11", "size": "3.3M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/stress-ng/924"}, {"filesystem": "tmpfs", "size": "197M", "used": 0, "available": null, "use_percent": 0, "mounted_on": "/run/user/1000"}, {"filesystem": "/dev/loop9", "size": "8.7M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/doctl/215"}, {"filesystem": "/dev/loop4", "size": "67M", "used": null, "available": 0, "use_percent": 100, "mounted_on": "/snap/google-cloud-sdk/104"}] +[{"filesystem":"udev","size":"955M","used":0,"mounted_on":"/dev","available":955,"use_percent":0},{"filesystem":"tmpfs","size":"198M","used":1,"mounted_on":"/run","available":196,"use_percent":1},{"filesystem":"/dev/sda2","size":"20G","used":6,"mounted_on":"/","available":14,"use_percent":30},{"filesystem":"tmpfs","size":"986M","used":0,"mounted_on":"/dev/shm","available":986,"use_percent":0},{"filesystem":"tmpfs","size":"5.0M","used":0,"mounted_on":"/run/lock","available":5,"use_percent":0},{"filesystem":"tmpfs","size":"986M","used":0,"mounted_on":"/sys/fs/cgroup","available":986,"use_percent":0},{"filesystem":"/dev/loop0","size":"55M","used":55,"mounted_on":"/snap/core18/1223","available":0,"use_percent":100},{"filesystem":"/dev/loop1","size":"11M","used":11,"mounted_on":"/snap/slcli/383","available":0,"use_percent":100},{"filesystem":"/dev/loop2","size":"89M","used":89,"mounted_on":"/snap/core/7396","available":0,"use_percent":100},{"filesystem":"/dev/loop3","size":"67M","used":67,"mounted_on":"/snap/google-cloud-sdk/103","available":0,"use_percent":100},{"filesystem":"/dev/loop5","size":"55M","used":55,"mounted_on":"/snap/core18/1074","available":0,"use_percent":100},{"filesystem":"/dev/loop7","size":"8.7M","used":9,"mounted_on":"/snap/doctl/187","available":0,"use_percent":100},{"filesystem":"/dev/loop8","size":"3.2M","used":3,"mounted_on":"/snap/stress-ng/847","available":0,"use_percent":100},{"filesystem":"/dev/loop10","size":"90M","used":90,"mounted_on":"/snap/core/7917","available":0,"use_percent":100},{"filesystem":"/dev/loop11","size":"3.3M","used":3,"mounted_on":"/snap/stress-ng/924","available":0,"use_percent":100},{"filesystem":"tmpfs","size":"197M","used":0,"mounted_on":"/run/user/1000","available":197,"use_percent":0},{"filesystem":"/dev/loop9","size":"8.7M","used":9,"mounted_on":"/snap/doctl/215","available":0,"use_percent":100},{"filesystem":"/dev/loop4","size":"67M","used":67,"mounted_on":"/snap/google-cloud-sdk/104","available":0,"use_percent":100}] diff --git a/tests/fixtures/ubuntu-18.04/free-h.json b/tests/fixtures/ubuntu-18.04/free-h.json index 4bc5380a..586bb889 100644 --- a/tests/fixtures/ubuntu-18.04/free-h.json +++ b/tests/fixtures/ubuntu-18.04/free-h.json @@ -1 +1 @@ -[{"type": "Mem", "total": null, "used": null, "free": null, "shared": null, "buff_cache": null, "available": null}, {"type": "Swap", "total": null, "used": null, "free": null}] +[{"type":"Mem","total":2,"used":237,"free":466,"shared":1,"buff_cache":1,"available":2},{"type":"Swap","total":2,"used":268,"free":2}]