iutwilio   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 279
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 203
dl 0
loc 279
rs 8.4
c 0
b 0
f 0
wmc 50

12 Functions

Rating   Name   Duplication   Size   Complexity  
A make_twilio() 0 3 1
A call() 0 9 2
B run() 0 18 7
A dump() 0 8 3
B parse_command_line() 0 66 4
A parse_xml() 0 5 1
A main() 0 8 2
A get_ini() 0 5 2
A setup() 0 12 4
A message() 0 11 2
A parse_ini() 0 17 5
F make_message() 0 50 17

How to fix   Complexity   

Complexity

Complex classes like iutwilio often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python
2
#
3
# iutwilio.py
4
#
5
# Copyright (C) 2015-2016, Takazumi Shirayanagi
6
# This software is released under the new BSD License,
7
# see LICENSE
8
#
9
10
import os
11
import sys
12
import xml.etree.ElementTree as ET
13
14
from argparse import ArgumentParser
15
from twilio.rest import TwilioRestClient
16
17
try:
18
    import configparser
19
except ImportError:
20
    import ConfigParser as configparser
21
22
account_sid = ''
23
auth_token = ''
24
my_number = ''
25
sms_number = ''
26
27
28
# command line option
29
def parse_command_line():
30
    parser = ArgumentParser()
31
    parser.add_argument(
32
        '-v',
33
        '--version',
34
        action='version',
35
        version=u'%(prog)s version 0.4'
36
    )
37
    parser.add_argument(
38
        '--ini',
39
        default='config.ini',
40
        help='ini file path. (inifile section [Twilio] account_sid,auth_token,number,sms_number)'
41
    )
42
    parser.add_argument(
43
        '--call',
44
        metavar='NUMBER',
45
        help='call to number.'
46
    )
47
    parser.add_argument(
48
        '--sms',
49
        metavar='NUMBER',
50
        help='send message number.'
51
    )
52
    parser.add_argument(
53
        '--account_sid',
54
        metavar='SID',
55
        help='account sid.'
56
    )
57
    parser.add_argument(
58
        '--auth_token',
59
        metavar='TOKEN',
60
        help='auth token.'
61
    )
62
    parser.add_argument(
63
        '--number',
64
        help='twilio phone number.'
65
    )
66
    parser.add_argument(
67
        '--dump',
68
        action='store_true',
69
        help='dump setting.'
70
    )
71
    parser.add_argument(
72
        '--dryrun',
73
        action='store_true',
74
        help='dryrun.'
75
    )
76
    parser.add_argument(
77
        '--url',
78
        default='http://twimlbin.com/2e6ad348',
79
        help='TwiML url.'
80
    )
81
    parser.add_argument(
82
        'xml',
83
        metavar='XML',
84
        nargs='?',
85
        help='test result xml file'
86
    )
87
    options = parser.parse_args()
88
89
    if not options.dump:
90
        if not options.xml:
91
            if not options.call:
92
                parser.print_help()
93
94
    return options
95
96
97
# setup
98
def setup(options):
99
    global account_sid
100
    global auth_token
101
    global my_number
102
    global sms_number
103
    if options.account_sid:
104
        account_sid = options.account_sid
105
    if options.auth_token:
106
        auth_token = options.auth_token
107
    if options.number:
108
        my_number = options.number
109
        sms_number = options.number
110
111
112
def get_ini(ini, s, n):
113
    try:
114
        return ini.get(s, n)
115
    except:
116
        return None
117
118
119
def parse_ini(path):
120
    global account_sid
121
    global auth_token
122
    global my_number
123
    global sms_number
124
    if account_sid and auth_token and my_number:
125
        return
126
    ini = configparser.SafeConfigParser()
127
    if not os.path.exists(path):
128
        sys.stderr.write('%s not found...' % path)
129
        sys.exit(2)
130
    ini.read(path)
131
132
    account_sid = get_ini(ini, 'Twilio', 'account_sid')
133
    auth_token = get_ini(ini, 'Twilio', 'auth_token')
134
    my_number = get_ini(ini, 'Twilio', 'number')
135
    sms_number = get_ini(ini, 'Twilio', 'sms_number')
136
137
#   for section in ini.sections():
138
#       print('[%s]' % (section))
139
#       for key in ini.options(section):
140
#           print('%s.%s =%s' % (section, key, ini.get(section, key)))
141
142
143
def parse_xml(path):
144
    tree = ET.parse(path)
145
    root = tree.getroot()
146
    testsuites = root.find('[@failures]')
147
    return testsuites.attrib['failures']
148
149
150
# make twilio client
151
def make_twilio():
152
    client = TwilioRestClient(account_sid, auth_token)
153
    return client
154
155
156
# call twilio
157
def call(client, options):
158
    if options.dryrun:
159
        print('twilio call to ' + options.call)
160
    else:
161
        call = client.calls.create(
162
            url=options.url,
163
            to=options.call,
164
            from_=my_number)
165
        print(call.sid)
166
167
168
# make_message
169
def make_message(options):
170
    body = ""
171
    filepath = options.xml
172
    if filepath and os.path.exists(filepath):
173
        tree = ET.parse(filepath)
174
        root = tree.getroot()
175
        tests = int(root.get('tests'))
176
        testcases = len(root.findall('testsuite'))
177
        failures = int(root.get('failures'))
178
        disabled = int(root.get('disabled'))
179
        skipped = int(root.get('skip'))
180
        passed = tests - failures - skipped
181
        time = root.get('time')
182
        timestamp = root.get('timestamp')
183
184
        if timestamp:
185
            body += "%s\n" % (timestamp)
186
        first_failure = None
187
188
        body += "%d tests from %s testcase ran. (%sms total)\n" % (tests, testcases, time)
189
        if passed:
190
            body += "PASSED  : %d\n" % (passed)
191
        if disabled:
192
            body += "DISABLED: %d\n" % (disabled)
193
        if skipped:
194
            body += "SKIPPED : %d\n" % (skipped)
195
        if failures:
196
            body += "FAILED  : %d\n" % (failures)
197
        failure_testsuites = root.findall('testsuite')
198
        for suite in failure_testsuites:
199
            if int(suite.get('failures')):
200
                for test in suite:
201
                    failure_node = test.find('.//failure')
202
                    if failure_node:
203
                        if not first_failure:
204
                            first_failure = failure_node
205
                        name = "%s.%s\n" % (suite.get('name'), test.get('name'))
206
                        if len(body) + len(name) < 155:
207
                            body += name
208
                        else:
209
                            body += "..."
210
                            return body
211
        if first_failure:
212
            for s in first_failure.text.split('\n'):
213
                if len(body) + len(s) < 155:
214
                    body += "%s\n" % s
215
                else:
216
                    body += "..."
217
                    return body
218
    return body
219
220
221
# message
222
def message(client, options):
223
    m = make_message(options)
224
    if options.dryrun:
225
        print('twilio call to ' + options.sms)
226
        print(m)
227
    else:
228
        call = client.messages.create(
229
            body=m,
230
            to=options.sms,
231
            from_=sms_number)
232
        print(call.sid)
233
234
235
# run
236
def run(options):
237
    filepath = options.xml
238
    if filepath:
239
        if not os.path.exists(filepath):
240
            sys.exit(1)
241
        else:
242
            if int(parse_xml(filepath)) > 0:
243
                if options.sms:
244
                    message(make_twilio(), options)
245
                elif options.call:
246
                    call(make_twilio(), options)
247
                else:
248
                    print('was failed ' + filepath)
249
    else:
250
        if options.call:
251
            call(make_twilio(), options)
252
253
    sys.exit(0)
254
255
256
# dump
257
def dump(options):
258
    print('account_sid: %s' % (account_sid))
259
    print('auth_token : %s' % (auth_token))
260
    print('my_number  : %s' % (my_number))
261
    if options.call:
262
        print('call       : %s' % (options.call))
263
    if options.sms:
264
        print('sms        : %s' % (options.sms))
265
266
267
def main():
268
    options = parse_command_line()
269
    setup(options)
270
    parse_ini(options.ini)
271
    if options.dump:
272
        dump(options)
273
    else:
274
        run(options)
275
276
277
if __name__ == '__main__':
278
    main()
279