-
Notifications
You must be signed in to change notification settings - Fork 0
/
reporter.py
110 lines (99 loc) · 3.3 KB
/
reporter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__app_name__ = 'Reporter'
__author__ = 'Markus Thilo'
__version__ = '0.5.1_2024-05-27'
__license__ = 'GPL-3'
__email__ = '[email protected]'
__status__ = 'Testing'
__description__ = '''
The tool parses a template and replaces %jinsert{}{} or \\jinsert{}{} (one backslash) by values from a JSON file.
Example: reporter-example-template.txt
'''
from json import load
from re import compile as regcompile
from argparse import ArgumentParser
from lib.extpath import ExtPath
from lib.timestamp import TimeStamp
class Reporter:
'''Parse JSON file throught template to generate report'''
def __init__(self):
'''Generate object'''
self.available = True
def parse(self, json, template):
'''Parse json through template'''
self.json_path = ExtPath.path(json)
self.template = ExtPath.path(template)
with self.json_path.open() as fh:
inserts = load(fh)
reg = regcompile('[%\\\\]jinsert\\{([^}]*)\\}\\{([^}]+)\\}')
self.parsed_text = ''
self.errors = 0
for line in self.template.read_text().splitlines():
newline = ''
position = 0
remove_line = False
for m in reg.finditer(line):
span = m.span()
groups = m.groups()
try:
insert_text = inserts[groups[1]]
except KeyError:
if groups[0] == 'r':
insert_text = ''
elif groups[0] == 'rl':
remove_line = True
break
else:
insert_text = f'### ERROR: unable to find a value for "{groups[1]}" ###'
self.errors += 1
newline += line[position:span[0]] + insert_text
position = span[1]
if not remove_line:
self.parsed_text += newline + line[position:] + '\n'
return self.parsed_text
def write(self, filename=None, outdir=None):
'''Write parsed file'''
self.outdir = ExtPath.mkdir(outdir)
if filename:
self.filename = filename
else:
self.filename = self.json_path.name
self.destination_path = (self.outdir/f'{self.filename}_report').with_suffix(self.template.suffix)
self.destination_path.write_text(self.parsed_text)
class ReporterCli(ArgumentParser):
'''CLI for EwfVerify'''
def __init__(self):
'''Define CLI using argparser'''
super().__init__(description=__description__, prog=__app_name__.lower())
self.add_argument('-f', '--filename', type=str,
help='Filename to generated (without extension)', metavar='STRING'
)
self.add_argument('-j', '--json', type=ExtPath.path, required=True,
help='JSON file to parse (required)', metavar='FILE'
)
self.add_argument('-o', '--outdir', type=ExtPath.path,
help='Directory to write generated files (STDOUT if not given)', metavar='DIRECTORY'
)
self.add_argument('template', nargs=1, type=ExtPath.path,
help='Template text file', metavar='FILE'
)
def parse(self, *cmd):
'''Parse arguments'''
args = super().parse_args(*cmd)
self.template = args.template[0]
self.json = args.json
self.filename = args.filename
self.outdir = args.outdir
def run(self, echo=print):
'''Run the verification'''
reporter = Reporter()
echo(reporter.parse(self.json, self.template))
if reporter.errors > 0:
raise RuntimeError(f'Parser reported {reporter.errors} error(s)')
if self.outdir or self.filename:
reporter.write(filename=self.filename, outdir=self.outdir)
if __name__ == '__main__': # start here if called as application
app = ReporterCli()
app.parse()
app.run()