1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-17 00:07:37 +02:00

add ver parser

This commit is contained in:
Kelly Brazil
2023-01-25 15:58:27 -08:00
parent 0e6cec62c1
commit a5a87c7da1
3 changed files with 155 additions and 2 deletions

View File

@ -1,8 +1,9 @@
jc changelog
20230122 v1.23.0
20230125 v1.23.0
- Add input slicing as a `jc` command-line option
- Add `ssh` configuration file parser
- Add input slicing
- Add `ver` Version string parser
- Fix `acpi` command parser for "will never fully discharge" battery state
20230111 v1.22.5

View File

@ -190,6 +190,7 @@ parsers: List[str] = [
'upower',
'uptime',
'url',
'ver',
'vmstat',
'vmstat-s',
'w',

151
jc/parsers/ver.py Normal file
View File

@ -0,0 +1,151 @@
"""jc - JSON Convert Version string output parser
Best effort attempt to parse various styles of version numbers. This parser
is based off of the version parser included in the CPython distutils
libary.
If the version string conforms to some de facto-standard versioning rules
followed by many developers a `strict` key will be present in the output
with a value of `true` along with the named parsed components.
All other version strings will have a `strict` value of `false` and a
`components` key will contain a list of detected parts of the version
string.
Usage (cli):
$ echo '1.2b' | jc --ver
Usage (module):
import jc
result = jc.parse('ver', version_string_output)
Schema:
[
{
"version": string,
"bar": boolean,
"baz": integer
}
]
Examples:
$ echo '1.2b' | jc --ver -p
[]
"""
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'Version string parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Based on distutils/version.py from CPython 3.9.5'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['generic', 'string']
__version__ = info.version
def _process(proc_data: JSONDictType) -> JSONDictType:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
return proc_data
def strict_parse(vstring):
version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', re.VERBOSE)
match = version_re.match(vstring)
if not match:
raise ValueError("invalid version number '%s'" % vstring)
(major, minor, patch, prerelease, prerelease_num) = \
match.group(1, 2, 4, 5, 6)
if patch:
version = tuple(map(int, [major, minor, patch]))
else:
version = tuple(map(int, [major, minor])) + (0,)
if prerelease:
prerelease = (prerelease[0], int(prerelease_num))
else:
prerelease = None
return {
'major': major,
'minor': minor,
'patch': patch,
'prerelease': prerelease,
'prerelease_num': prerelease_num
}
def loose_parse(vstring):
component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
components = [x for x in component_re.split(vstring) if x and x != '.']
return components
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> JSONDictType:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: Dict = {}
strict = True
if jc.utils.has_data(data):
# based on distutils/version.py from CPython 3.9.5
# PSF License (see https://opensource.org/licenses/Python-2.0)
data = data.strip()
try:
raw_output = strict_parse(data)
except ValueError:
raw_output['components'] = loose_parse(data)
strict = False
if raw_output:
raw_output['strict'] = strict
return raw_output if raw else _process(raw_output)