iutwilio.run()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 14
nop 1
dl 0
loc 18
rs 8
c 0
b 0
f 0
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 Exception as e:
116
        print(e)
117
        return None
118
119
120
def parse_ini(path):
121
    global account_sid
122
    global auth_token
123
    global my_number
124
    global sms_number
125
    if account_sid and auth_token and my_number:
126
        return
127
    ini = configparser.SafeConfigParser()
128
    if not os.path.exists(path):
129
        sys.stderr.write('%s not found...' % path)
130
        sys.exit(2)
131
    ini.read(path)
132
133
    account_sid = get_ini(ini, 'Twilio', 'account_sid')
134
    auth_token = get_ini(ini, 'Twilio', 'auth_token')
135
    my_number = get_ini(ini, 'Twilio', 'number')
136
    sms_number = get_ini(ini, 'Twilio', 'sms_number')
137
138
#   for section in ini.sections():
139
#       print('[%s]' % (section))
140
#       for key in ini.options(section):
141
#           print('%s.%s =%s' % (section, key, ini.get(section, key)))
142
143
144
def parse_xml(path):
145
    tree = ET.parse(path)
146
    root = tree.getroot()
147
    testsuites = root.find('[@failures]')
148
    return testsuites.attrib['failures']
149
150
151
# make twilio client
152
def make_twilio():
153
    client = TwilioRestClient(account_sid, auth_token)
154
    return client
155
156
157
# call twilio
158
def call(client, options):
159
    if options.dryrun:
160
        print('twilio call to ' + options.call)
161
    else:
162
        call = client.calls.create(
163
            url=options.url,
164
            to=options.call,
165
            from_=my_number)
166
        print(call.sid)
167
168
169
# make_message
170
def make_message(options):
171
    body = ""
172
    filepath = options.xml
173
    if filepath and os.path.exists(filepath):
174
        tree = ET.parse(filepath)
175
        root = tree.getroot()
176
        tests = int(root.get('tests'))
177
        testcases = len(root.findall('testsuite'))
178
        failures = int(root.get('failures'))
179
        disabled = int(root.get('disabled'))
180
        skipped = int(root.get('skip'))
181
        passed = tests - failures - skipped
182
        time = root.get('time')
183
        timestamp = root.get('timestamp')
184
185
        if timestamp:
186
            body += "%s\n" % (timestamp)
187
        first_failure = None
188
189
        body += "%d tests from %s testcase ran. (%sms total)\n" % (tests, testcases, time)
190
        if passed:
191
            body += "PASSED  : %d\n" % (passed)
192
        if disabled:
193
            body += "DISABLED: %d\n" % (disabled)
194
        if skipped:
195
            body += "SKIPPED : %d\n" % (skipped)
196
        if failures:
197
            body += "FAILED  : %d\n" % (failures)
198
        failure_testsuites = root.findall('testsuite')
199
        for suite in failure_testsuites:
200
            if int(suite.get('failures')):
201
                for test in suite:
202
                    failure_node = test.find('.//failure')
203
                    if failure_node:
204
                        if not first_failure:
205
                            first_failure = failure_node
206
                        name = "%s.%s\n" % (suite.get('name'), test.get('name'))
207
                        if len(body) + len(name) < 155:
208
                            body += name
209
                        else:
210
                            body += "..."
211
                            return body
212
        if first_failure:
213
            for s in first_failure.text.split('\n'):
214
                if len(body) + len(s) < 155:
215
                    body += "%s\n" % s
216
                else:
217
                    body += "..."
218
                    return body
219
    return body
220
221
222
# message
223
def message(client, options):
224
    m = make_message(options)
225
    if options.dryrun:
226
        print('twilio call to ' + options.sms)
227
        print(m)
228
    else:
229
        call = client.messages.create(
230
            body=m,
231
            to=options.sms,
232
            from_=sms_number)
233
        print(call.sid)
234
235
236
# run
237
def run(options):
238
    filepath = options.xml
239
    if filepath:
240
        if not os.path.exists(filepath):
241
            sys.exit(1)
242
        else:
243
            if int(parse_xml(filepath)) > 0:
244
                if options.sms:
245
                    message(make_twilio(), options)
246
                elif options.call:
247
                    call(make_twilio(), options)
248
                else:
249
                    print('was failed ' + filepath)
250
    else:
251
        if options.call:
252
            call(make_twilio(), options)
253
254
    sys.exit(0)
255
256
257
# dump
258
def dump(options):
259
    print('account_sid: %s' % (account_sid))
260
    print('auth_token : %s' % (auth_token))
261
    print('my_number  : %s' % (my_number))
262
    if options.call:
263
        print('call       : %s' % (options.call))
264
    if options.sms:
265
        print('sms        : %s' % (options.sms))
266
267
268
def main():
269
    options = parse_command_line()
270
    setup(options)
271
    parse_ini(options.ini)
272
    if options.dump:
273
        dump(options)
274
    else:
275
        run(options)
276
277
278
if __name__ == '__main__':
279
    main()
280