Passed
Push — master ( 0e1758...22656e )
by srz
06:22
created

xml2file.xml2file()   B

Complexity

Conditions 5

Size

Total Lines 23
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 21
nop 1
dl 0
loc 23
rs 8.9093
c 0
b 0
f 0
1
#!/usr/bin/env python
2
#
3
# xml2file.py
4
#
5
# Copyright (C) 2019, Takazumi Shirayanagi
6
# This software is released under the new BSD License,
7
# see LICENSE
8
#
9
10
import os
11
import errno
12
import json
13
import codecs
14
import shutil
15
import xml.etree.ElementTree as ET
16
17
from argparse import ArgumentParser
18
19
# command line option
20 View Code Duplication
def parse_command_line():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
21
    parser = ArgumentParser()
22
    parser.add_argument(
23
        '-v',
24
        '--version',
25
        action='version',
26
        version=u'%(prog)s version 0.1'
27
    )
28
    parser.add_argument(
29
        '-o',
30
        '--output',
31
        default=None,
32
        help='output file path.'
33
    )
34
    parser.add_argument(
35
        '--no-time',
36
        action='store_true',
37
        help='no output time attribute'
38
    )
39
    parser.add_argument(
40
        '--verbose',
41
        action='store_true',
42
        help='log verbose'
43
    )
44
    parser.add_argument(
45
        '--encoding',
46
        default=None,
47
        help='output file encoding.'
48
    )
49
    parser.add_argument(
50
        '--debug',
51
        action='store_true',
52
        help='log debug'
53
    )
54
    parser.add_argument(
55
        'file',
56
        metavar='FILE',
57
        nargs='+',
58
        help='test result xml files'
59
    )
60
    options = parser.parse_args()
61
    return options
62
63
cmdline_options = None
64
65
66
def log(msg):
67
    if cmdline_options.verbose:
68
        print(msg)
69
70
71
def logd(msg):
72
    if cmdline_options.debug:
73
        print(msg)
74
75
76
def mkdir_p(path):
77
    try:
78
        os.makedirs(path)
79
    except OSError as exc:  # Python >2.5
80
        if exc.errno == errno.EEXIST and os.path.isdir(path):
81
            pass
82
        else:
83
            raise
84
85
86
def clean_dir(path):
87
    if os.path.exists(path):
88
        shutil.rmtree(path)
89
90
91
def fopen(path):
92
    dir = os.path.dirname(path)
93
    mkdir_p(dir)
94
    f = codecs.open(path, 'w', cmdline_options.encoding)
95
    return f
96
97
98
def make_rootpath(xml_filename, testsuites):
99
    # root_name = testsuites.attrib['name']
100
    root_name = xml_filename
101
    path = os.path.join(cmdline_options.output, root_name)
102
    return path
103
104
105
def make_path(root_path, testsuite, testcase):
106
    suite_name = testsuite.attrib['name']
107
    case_name = testcase.attrib['name']
108
    ext = '.json'
109
    return os.path.join(os.path.join(root_path, suite_name), case_name + ext)
110
111
112
def get_properties_node(node):
113
    users = {}
114
    for prop in node:
115
        if ('name' in prop.attrib) and ('value' in prop.attrib):
116
            users[prop.attrib['name']] = prop.attrib['value']
117
    return users
118
119
120
def _get_user_properties(node, system_attributes):
121
    users = {}
122
    for a in node.attrib:
123
        if a not in system_attributes:
124
            users[a] = node.attrib[a]
125
    return users
126
127
128
def get_user_properties(node):
129
    system_attributes = {
130
        "testsuites": [
131
            "name", "tests", "failures", "disabled", "skip", "errors", "time", "timestamp", "random_seed"
132
        ],
133
        "testsuite": [
134
            "name", "tests", "failures", "disabled", "skip", "errors", "time", "timestamp", "random_seed"
135
        ],
136
        "testcase": [
137
            "name", "status", "time", "classname", "type_param", "value_param"
138
        ]
139
    }
140
    for k,v in system_attributes.items():
141
        if node.tag == k:
142
            return _get_user_properties(node, v)
143
    return node.attrib
144
145
146
def write_result(f, testsuites_user_attrib, testsuite_user_attrib, testcase):
147
    d = testcase.attrib
148
    if cmdline_options.no_time:
149
        if 'time' in d:
150
            del d['time']
151
    d['testsuites_attrib'] = testsuites_user_attrib
152
    d['testsuite_attrib'] = testsuite_user_attrib
153
    # failure and skipped ...
154
    for child in testcase:
155
        tag = child.tag
156
        if tag not in d:
157
            d[tag] = []
158
        fd = child.attrib
159
        fd['text'] = child.text
160
        d[tag].append(fd)
161
    jt = json.dumps(d, indent=4, ensure_ascii=False)
162
    logd(jt)
163
    f.write(jt)
164
165
166
def xml2file(path):
167
    tree = ET.parse(path)
168
    root = tree.getroot()
169
    testsuites = root
170
171
    basename = os.path.basename(path)
172
    filename = os.path.splitext(basename)[0]
173
    root_path = make_rootpath(filename, testsuites)
174
    clean_dir(root_path)
175
176
    log(basename)
177
    testsuites_user_attrib = get_user_properties(testsuites)
178
    for testsuite in testsuites:
179
        log("  " + testsuite.attrib['name'])
180
        testsuite_user_attrib = get_user_properties(testsuite)
181
        for testcase in testsuite:
182
            if testcase.tag == 'testcase':
183
                log("    " + testcase.attrib['name'])
184
                f = fopen(make_path(root_path, testsuite, testcase))
185
                write_result(f, testsuites_user_attrib, testsuite_user_attrib, testcase)
186
                f.close()
187
            elif testcase.tag == 'properties':
188
                testsuite_user_attrib.update(get_properties_node(testcase))
189
190
191
def main():
192
    global cmdline_options
193
    cmdline_options = parse_command_line()
194
    for path in cmdline_options.file:
195
        xml2file(path)
196
197
198
if __name__ == '__main__':
199
    main()
200