Skip to content

Commit

Permalink
fix file_stats in git-log parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
kellyjonbrazil committed May 15, 2024
1 parent 0faacb6 commit f1bab33
Show file tree
Hide file tree
Showing 21 changed files with 113 additions and 41 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
jc changelog

20240510 v1.25.3
- Add `battery_percentage` field to `bluetoothctl` parser output
- Enhance `bluetoothctl` parser with added `battery_percentage` field
- Enhance `git-log` standard and streaming parsers with added `lines_changed` field under `file_stats`
- Fix `pci-ids` parser to correctly handle multiple subdevices
- Fix `pip-show` parser to handle multi-line fields with a beginning blank line
- Fix `top` parsers to quiet uptime info parsing
Expand Down
8 changes: 7 additions & 1 deletion docs/parsers/git_log.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ Schema:
"deletions": integer,
"files": [
string
],
"file_stats": [
{
"name": string,
"lines_changed": integer
}
]
}
}
Expand Down Expand Up @@ -174,4 +180,4 @@ Compatibility: linux, darwin, cygwin, win32, aix, freebsd

Source: [`jc/parsers/git_log.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/git_log.py)

Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
8 changes: 7 additions & 1 deletion docs/parsers/git_log_s.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ Schema:
"deletions": integer,
"files": [
string
],
"file_stats": [
{
"name": string,
"lines_changed": integer
}
]
}

Expand Down Expand Up @@ -109,4 +115,4 @@ Compatibility: linux, darwin, cygwin, win32, aix, freebsd

Source: [`jc/parsers/git_log_s.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/git_log_s.py)

Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
59 changes: 41 additions & 18 deletions jc/parsers/git_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
"deletions": integer,
"files": [
string
],
"file_stats": [
{
"name": string,
"lines_changed": integer
}
]
}
}
Expand Down Expand Up @@ -145,15 +151,15 @@
]
"""
import re
from typing import List, Dict
from typing import List, Dict, Any
import jc.utils

hash_pattern = re.compile(r'(?:[0-9]|[a-f]){40}')
changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed)(?:,\s+(?P<insertions>\d+)\s+(insertions?\(\+\)))?(?:,\s+(?P<deletions>\d+)\s+(deletions?\(\-\)))?')

class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.4'
version = '1.5'
description = '`git log` command parser'
author = 'Kelly Brazil'
author_email = '[email protected]'
Expand All @@ -177,7 +183,7 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
List of Dictionaries. Structured to conform to the schema.
"""
int_list = {'files_changed', 'insertions', 'deletions'}
int_list = {'files_changed', 'insertions', 'deletions', 'lines_changed'}

for entry in proc_data:
if 'date' in entry:
Expand All @@ -190,6 +196,13 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
if key in int_list:
entry['stats'][key] = jc.utils.convert_to_int(entry['stats'][key])

if 'file_stats' in entry['stats']:
file_stats = entry['stats']['file_stats']
for file_entry in file_stats:
for key in file_entry:
if key in int_list:
file_entry[key] = jc.utils.convert_to_int(file_entry[key])

return proc_data


Expand Down Expand Up @@ -251,6 +264,7 @@ def parse(
output_line: Dict = {}
message_lines: List[str] = []
file_list: List[str] = []
file_stats_list: List[Dict[str, Any]] = []

if jc.utils.has_data(data):

Expand All @@ -263,10 +277,14 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

raw_output.append(output_line)
output_line = {}
message_lines = []
file_list = []
file_stats_list = []
output_line = {
'commit': line_list[0],
'message': line_list[1]
Expand All @@ -282,10 +300,14 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

raw_output.append(output_line)
output_line = {}
message_lines = []
file_list = []
file_stats_list = []
output_line['commit'] = line_list[1]
continue

Expand Down Expand Up @@ -319,21 +341,19 @@ def parse(

if line.startswith(' ') and 'changed, ' not in line:
# this is a file name
file_name = line.split('|')[0].strip()
file_stats = line.split('|')[1].strip()
lines_changed_str = file_stats.split(' ')
lines_changed_count_str = lines_changed_str[0].strip()
lines_changed = 0
try:
lines_changed = int(lines_changed_count_str)
except:
#nothing to do
pass

file = {}
file["name"] = file_name
file["lines_changed"] = lines_changed
file_list.append(file)
file_line_split = line.split('|')
file_name = file_line_split[0].strip()
file_list.append(file_name)

if len(file_line_split) > 1:
file_stats = file_line_split[1].strip()
lines_changed_str = file_stats.split(' ')
lines_changed_count_str = lines_changed_str[0].strip()

file_stat = {}
file_stat["name"] = file_name
file_stat["lines_changed"] = lines_changed_count_str
file_stats_list.append(file_stat)
continue

if line.startswith(' ') and 'changed, ' in line:
Expand All @@ -357,6 +377,9 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

raw_output.append(output_line)

return raw_output if raw else _process(raw_output)
44 changes: 40 additions & 4 deletions jc/parsers/git_log_s.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
"deletions": integer,
"files": [
string
],
"file_stats": [
{
"name": string,
"lines_changed": integer
}
]
}
Expand All @@ -73,7 +79,7 @@
...
"""
import re
from typing import List, Dict, Iterable, Union
from typing import List, Dict, Any, Iterable, Union
import jc.utils
from jc.parsers.git_log import _parse_name_email
from jc.streaming import (
Expand All @@ -88,7 +94,7 @@

class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.4'
version = '1.5'
description = '`git log` command streaming parser'
author = 'Kelly Brazil'
author_email = '[email protected]'
Expand All @@ -112,7 +118,7 @@ def _process(proc_data: Dict) -> Dict:
Dictionary. Structured data to conform to the schema.
"""
int_list = {'files_changed', 'insertions', 'deletions'}
int_list = {'files_changed', 'insertions', 'deletions', 'lines_changed'}

if 'date' in proc_data:
ts = jc.utils.timestamp(proc_data['date'], format_hint=(1100,))
Expand All @@ -124,6 +130,13 @@ def _process(proc_data: Dict) -> Dict:
if key in int_list:
proc_data['stats'][key] = jc.utils.convert_to_int(proc_data['stats'][key])

if 'file_stats' in proc_data['stats']:
file_stats = proc_data['stats']['file_stats']
for file_entry in file_stats:
for key in file_entry:
if key in int_list:
file_entry[key] = jc.utils.convert_to_int(file_entry[key])

return proc_data


Expand Down Expand Up @@ -168,6 +181,7 @@ def parse(
output_line: Dict = {}
message_lines: List[str] = []
file_list: List[str] = []
file_stats_list: List[Dict[str, Any]] = []

for line in data:
try:
Expand All @@ -184,11 +198,15 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

yield output_line if raw else _process(output_line)

output_line = {}
message_lines = []
file_list = []
file_stats_list = []
output_line = {
'commit': line_list[0],
'message': line_list[1]
Expand All @@ -204,11 +222,15 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

yield output_line if raw else _process(output_line)

output_line = {}
message_lines = []
file_list = []
file_stats_list = []
output_line['commit'] = line_list[1]
continue

Expand Down Expand Up @@ -242,8 +264,19 @@ def parse(

if line.startswith(' ') and 'changed, ' not in line:
# this is a file name
file_name = line.split('|')[0].strip()
file_line_split = line.split('|')
file_name = file_line_split[0].strip()
file_list.append(file_name)

if len(file_line_split) > 1:
file_stats = file_line_split[1].strip()
lines_changed_str = file_stats.split(' ')
lines_changed_count_str = lines_changed_str[0].strip()

file_stat = {}
file_stat["name"] = file_name
file_stat["lines_changed"] = lines_changed_count_str
file_stats_list.append(file_stat)
continue

if line.startswith(' ') and 'changed, ' in line:
Expand Down Expand Up @@ -274,6 +307,9 @@ def parse(
if file_list:
output_line['stats']['files'] = file_list

if file_stats_list:
output_line['stats']['file_stats'] = file_stats_list

yield output_line if raw else _process(output_line)

except Exception as e:
Expand Down
2 changes: 1 addition & 1 deletion man/jc.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH jc 1 2024-05-10 1.25.3 "JSON Convert"
.TH jc 1 2024-05-14 1.25.3 "JSON Convert"
.SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types,
and strings
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/generic/git-log-full-stat-streaming.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/fixtures/generic/git-log-full-stat.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/fixtures/generic/git-log-fuller-stat-streaming.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/fixtures/generic/git-log-fuller-stat.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"commit":"e05824a36ca62aa9f3a21854ec8b40a3e0f7a68d","author":"Benedikt Heine","author_email":"[email protected]","date":"Mon Oct 28 12:42:22 2019 +0100","commit_by":"Benedikt Heine","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 17:27:16 2020 +0200","stats":{"files_changed":1,"insertions":13,"deletions":3,"files":["salt/modules/monit.py"]},"message":"Split monit status fields on monit version\n\nWith the commit [0] on monit, the field size changed. So splitting hard\nafter 35 chars, new versions of monit break when using monit.status.\n\n[0] https://bitbucket.org/tildeslash/monit/commits/\n471c4bbc388c1c536f07ce1dd26b811bd39a9467","epoch":1572291742,"epoch_utc":null},{"commit":"910a2ac4809bb05b886adfe75f4857eb53fdfbb1","merge":"6c3964ce30 f0a1e923e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:37 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:37 2020 -0700","message":"Merge pull request #53911 from terminalmage/squelch-log\n\nalternatives: Don't log error when running \"alternatives --display\" on nonexistant target","epoch":1586675377,"epoch_utc":null},{"commit":"6c3964ce30929e749c0965bc0d60527e9fe8dbb1","merge":"3026c25faf 2ac4da54e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:16 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:16 2020 -0700","message":"Merge pull request #54199 from driskell/patch-2\n\nFix broken sdb.get_or_set_hash for Hashicorp Vault","epoch":1586675356,"epoch_utc":null}]
[{"commit":"e05824a36ca62aa9f3a21854ec8b40a3e0f7a68d","author":"Benedikt Heine","author_email":"[email protected]","date":"Mon Oct 28 12:42:22 2019 +0100","commit_by":"Benedikt Heine","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 17:27:16 2020 +0200","stats":{"files_changed":1,"insertions":13,"deletions":3,"files":["salt/modules/monit.py"],"file_stats":[{"name":"salt/modules/monit.py","lines_changed":16}]},"message":"Split monit status fields on monit version\n\nWith the commit [0] on monit, the field size changed. So splitting hard\nafter 35 chars, new versions of monit break when using monit.status.\n\n[0] https://bitbucket.org/tildeslash/monit/commits/\n471c4bbc388c1c536f07ce1dd26b811bd39a9467","epoch":1572291742,"epoch_utc":null},{"commit":"910a2ac4809bb05b886adfe75f4857eb53fdfbb1","merge":"6c3964ce30 f0a1e923e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:37 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:37 2020 -0700","message":"Merge pull request #53911 from terminalmage/squelch-log\n\nalternatives: Don't log error when running \"alternatives --display\" on nonexistant target","epoch":1586675377,"epoch_utc":null},{"commit":"6c3964ce30929e749c0965bc0d60527e9fe8dbb1","merge":"3026c25faf 2ac4da54e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:16 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:16 2020 -0700","message":"Merge pull request #54199 from driskell/patch-2\n\nFix broken sdb.get_or_set_hash for Hashicorp Vault","epoch":1586675356,"epoch_utc":null}]
2 changes: 1 addition & 1 deletion tests/fixtures/generic/git-log-hash-in-message-fix.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"commit":"e05824a36ca62aa9f3a21854ec8b40a3e0f7a68d","author":"Benedikt Heine","author_email":"[email protected]","date":"Mon Oct 28 12:42:22 2019 +0100","commit_by":"Benedikt Heine","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 17:27:16 2020 +0200","stats":{"files_changed":1,"insertions":13,"deletions":3,"files":["salt/modules/monit.py"]},"message":"Split monit status fields on monit version\n\nWith the commit [0] on monit, the field size changed. So splitting hard\nafter 35 chars, new versions of monit break when using monit.status.\n\n[0] https://bitbucket.org/tildeslash/monit/commits/\n471c4bbc388c1c536f07ce1dd26b811bd39a9467","epoch":1572291742,"epoch_utc":null},{"commit":"910a2ac4809bb05b886adfe75f4857eb53fdfbb1","merge":"6c3964ce30 f0a1e923e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:37 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:37 2020 -0700","message":"Merge pull request #53911 from terminalmage/squelch-log\n\nalternatives: Don't log error when running \"alternatives --display\" on nonexistant target","epoch":1586675377,"epoch_utc":null},{"commit":"6c3964ce30929e749c0965bc0d60527e9fe8dbb1","merge":"3026c25faf 2ac4da54e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:16 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:16 2020 -0700","message":"Merge pull request #54199 from driskell/patch-2\n\nFix broken sdb.get_or_set_hash for Hashicorp Vault","epoch":1586675356,"epoch_utc":null}]
[{"commit":"e05824a36ca62aa9f3a21854ec8b40a3e0f7a68d","author":"Benedikt Heine","author_email":"[email protected]","date":"Mon Oct 28 12:42:22 2019 +0100","commit_by":"Benedikt Heine","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 17:27:16 2020 +0200","stats":{"files_changed":1,"insertions":13,"deletions":3,"files":["salt/modules/monit.py"],"file_stats":[{"name":"salt/modules/monit.py","lines_changed":16}]},"message":"Split monit status fields on monit version\n\nWith the commit [0] on monit, the field size changed. So splitting hard\nafter 35 chars, new versions of monit break when using monit.status.\n\n[0] https://bitbucket.org/tildeslash/monit/commits/\n471c4bbc388c1c536f07ce1dd26b811bd39a9467","epoch":1572291742,"epoch_utc":null},{"commit":"910a2ac4809bb05b886adfe75f4857eb53fdfbb1","merge":"6c3964ce30 f0a1e923e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:37 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:37 2020 -0700","message":"Merge pull request #53911 from terminalmage/squelch-log\n\nalternatives: Don't log error when running \"alternatives --display\" on nonexistant target","epoch":1586675377,"epoch_utc":null},{"commit":"6c3964ce30929e749c0965bc0d60527e9fe8dbb1","merge":"3026c25faf 2ac4da54e3","author":"Daniel Wozniak","author_email":"[email protected]","date":"Sun Apr 12 00:09:16 2020 -0700","commit_by":"GitHub","commit_by_email":"[email protected]","commit_by_date":"Sun Apr 12 00:09:16 2020 -0700","message":"Merge pull request #54199 from driskell/patch-2\n\nFix broken sdb.get_or_set_hash for Hashicorp Vault","epoch":1586675356,"epoch_utc":null}]
Loading

0 comments on commit f1bab33

Please sign in to comment.