core.rule   F
last analyzed

Complexity

Total Complexity 77

Size/Duplication

Total Lines 339
Duplicated Lines 7.67 %

Importance

Changes 0
Metric Value
eloc 267
dl 26
loc 339
rs 2.24
c 0
b 0
f 0
wmc 77

9 Methods

Rating   Name   Duplication   Size   Complexity  
A RuleCollection.on_options() 0 3 1
A RuleCollection.__init__() 0 3 1
A RuleCollection.on_get() 0 27 4
A RuleItem.on_delete() 26 26 4
A RuleItem.on_options() 0 3 1
A RuleItem.__init__() 0 3 1
A RuleItem.on_get() 0 28 4
F RuleItem.on_put() 0 120 32
F RuleCollection.on_post() 0 107 29

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like core.rule 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
import falcon
2
import json
3
import mysql.connector
4
import config
5
import uuid
6
7
8
class RuleCollection:
9
    @staticmethod
10
    def __init__():
11
        pass
12
13
    @staticmethod
14
    def on_options(req, resp):
15
        resp.status = falcon.HTTP_200
16
17
    @staticmethod
18
    def on_get(req, resp):
19
        cnx = mysql.connector.connect(**config.myems_fdd_db)
20
        cursor = cnx.cursor(dictionary=True)
21
22
        query = (" SELECT id, name, uuid, "
23
                 "        fdd_code, category, priority, "
24
                 "        channel, expression, message_template, "
25
                 "        is_enabled "
26
                 " FROM tbl_rules "
27
                 " ORDER BY id ")
28
        cursor.execute(query)
29
        rows = cursor.fetchall()
30
        cursor.close()
31
        cnx.disconnect()
32
33
        result = list()
34
        if rows is not None and len(rows) > 0:
35
            for row in rows:
36
                meta_result = {"id": row['id'], "name": row['name'], "uuid": row['uuid'],
37
                               "fdd_code": row['fdd_code'], "category": row['category'], "priority": row['priority'],
38
                               "channel": row['channel'], "expression": row['expression'],
39
                               "message_template": row['message_template'].replace("<br>", ""),
40
                               "is_enabled": bool(row['is_enabled'])}
41
                result.append(meta_result)
42
43
        resp.body = json.dumps(result)
44
45
    @staticmethod
46
    def on_post(req, resp):
47
        """Handles POST requests"""
48
        try:
49
            raw_json = req.stream.read().decode('utf-8')
50
        except Exception as ex:
51
            raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=ex)
52
53
        new_values = json.loads(raw_json)
54
        if 'name' not in new_values['data'].keys() or \
55
                not isinstance(new_values['data']['name'], str) or \
56
                len(str.strip(new_values['data']['name'])) == 0:
57
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
58
                                   description='API.INVALID_RULE_NAME')
59
        name = str.strip(new_values['data']['name'])
60
61
        if 'fdd_code' not in new_values['data'].keys() or \
62
                not isinstance(new_values['data']['fdd_code'], str) or \
63
                len(str.strip(new_values['data']['fdd_code'])) == 0:
64
            raise falcon.HTTPError(falcon.HTTP_400,
65
                                   title='API.BAD_REQUEST',
66
                                   description='API.INVALID_FDD_CODE')
67
        fdd_code = str.strip(new_values['data']['fdd_code'])
68
69
        if 'category' not in new_values['data'].keys() or \
70
                not isinstance(new_values['data']['category'], str) or \
71
                len(str.strip(new_values['data']['category'])) == 0 or \
72
                str.strip(new_values['data']['category']) not in \
73
                ('SYSTEM', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', 'COMBINEDEQUIPMENT'):
74
            raise falcon.HTTPError(falcon.HTTP_400,
75
                                   title='API.BAD_REQUEST',
76
                                   description='API.INVALID_CATEGORY')
77
        category = str.strip(new_values['data']['category'])
78
79
        if 'priority' not in new_values['data'].keys() or \
80
                not isinstance(new_values['data']['priority'], str) or \
81
                len(str.strip(new_values['data']['priority'])) == 0 or \
82
                str.strip(new_values['data']['priority']) not in \
83
                ('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'):
84
            raise falcon.HTTPError(falcon.HTTP_400,
85
                                   title='API.BAD_REQUEST',
86
                                   description='API.INVALID_PRIORITY')
87
        priority = str.strip(new_values['data']['priority'])
88
89
        if 'channel' not in new_values['data'].keys() or \
90
                not isinstance(new_values['data']['channel'], str) or \
91
                len(str.strip(new_values['data']['channel'])) == 0 or \
92
                str.strip(new_values['data']['channel']) not in ('WEB', 'EMAIL', 'SMS', 'WECHAT', 'CALL'):
93
            raise falcon.HTTPError(falcon.HTTP_400,
94
                                   title='API.BAD_REQUEST',
95
                                   description='API.INVALID_CHANNEL')
96
        channel = str.strip(new_values['data']['channel'])
97
98
        if 'expression' not in new_values['data'].keys() or \
99
                not isinstance(new_values['data']['expression'], str) or \
100
                len(str.strip(new_values['data']['expression'])) == 0:
101
            raise falcon.HTTPError(falcon.HTTP_400,
102
                                   title='API.BAD_REQUEST',
103
                                   description='API.INVALID_EXPRESSION')
104
        expression = str.strip(new_values['data']['expression'])
105
106
        if 'message_template' not in new_values['data'].keys() or \
107
                not isinstance(new_values['data']['message_template'], str) or \
108
                len(str.strip(new_values['data']['message_template'])) == 0:
109
            raise falcon.HTTPError(falcon.HTTP_400,
110
                                   title='API.BAD_REQUEST',
111
                                   description='API.INVALID_MESSAGE_TEMPLATE')
112
        message_template = str.strip(new_values['data']['message_template'])
113
114
        if 'is_enabled' not in new_values['data'].keys() or \
115
                not isinstance(new_values['data']['is_enabled'], bool):
116
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
117
                                   description='API.INVALID_IS_ENABLED')
118
        is_enabled = new_values['data']['is_enabled']
119
120
        cnx = mysql.connector.connect(**config.myems_fdd_db)
121
        cursor = cnx.cursor()
122
123
        cursor.execute(" SELECT name "
124
                       " FROM tbl_rules "
125
                       " WHERE name = %s ", (name,))
126
        if cursor.fetchone() is not None:
127
            cursor.close()
128
            cnx.disconnect()
129
            raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST',
130
                                   description='API.RULE_NAME_IS_ALREADY_IN_USE')
131
132
        add_row = (" INSERT INTO tbl_rules "
133
                   "             (name, uuid, fdd_code, category, priority, "
134
                   "              channel, expression, message_template, is_enabled) "
135
                   " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) ")
136
        cursor.execute(add_row, (name,
137
                                 str(uuid.uuid4()),
138
                                 fdd_code,
139
                                 category,
140
                                 priority,
141
                                 channel,
142
                                 expression,
143
                                 message_template,
144
                                 is_enabled))
145
        new_id = cursor.lastrowid
146
        cnx.commit()
147
        cursor.close()
148
        cnx.disconnect()
149
150
        resp.status = falcon.HTTP_201
151
        resp.location = '/rules/' + str(new_id)
152
153
154
class RuleItem:
155
    @staticmethod
156
    def __init__():
157
        pass
158
159
    @staticmethod
160
    def on_options(req, resp, id_):
161
        resp.status = falcon.HTTP_200
162
163
    @staticmethod
164
    def on_get(req, resp, id_):
165
        if not id_.isdigit() or int(id_) <= 0:
166
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
167
                                   description='API.INVALID_RULE_ID')
168
169
        cnx = mysql.connector.connect(**config.myems_fdd_db)
170
        cursor = cnx.cursor(dictionary=True)
171
172
        query = (" SELECT id, name, uuid, "
173
                 "        fdd_code, category, priority, "
174
                 "        channel, expression, message_template, is_enabled "
175
                 " FROM tbl_rules "
176
                 " WHERE id = %s ")
177
        cursor.execute(query, (id_,))
178
        row = cursor.fetchone()
179
        cursor.close()
180
        cnx.disconnect()
181
        if row is None:
182
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
183
                                   description='API.RULE_NOT_FOUND')
184
185
        result = {"id": row['id'], "name": row['name'], "uuid": row['uuid'],
186
                  "fdd_code": row['fdd_code'], "category": row['category'], "priority": row['priority'],
187
                  "channel": row['channel'], "expression": row['expression'],
188
                  "message_template": row['message_template'].replace("<br>", ""),
189
                  "is_enabled": bool(row['is_enabled'])}
190
        resp.body = json.dumps(result)
191
192 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
193
    def on_delete(req, resp, id_):
194
        if not id_.isdigit() or int(id_) <= 0:
195
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
196
                                   description='API.INVALID_RULE_ID')
197
198
        cnx = mysql.connector.connect(**config.myems_fdd_db)
199
        cursor = cnx.cursor()
200
201
        cursor.execute(" SELECT id "
202
                       " FROM tbl_rules "
203
                       " WHERE id = %s ",
204
                       (id_,))
205
        if cursor.fetchone() is None:
206
            cursor.close()
207
            cnx.disconnect()
208
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
209
                                   description='API.RULE_NOT_FOUND')
210
211
        cursor.execute(" DELETE FROM tbl_rules WHERE id = %s ", (id_,))
212
        cnx.commit()
213
214
        cursor.close()
215
        cnx.disconnect()
216
217
        resp.status = falcon.HTTP_204
218
219
    @staticmethod
220
    def on_put(req, resp, id_):
221
        """Handles PUT requests"""
222
        try:
223
            raw_json = req.stream.read().decode('utf-8')
224
        except Exception as ex:
225
            raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=ex)
226
227
        if not id_.isdigit() or int(id_) <= 0:
228
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
229
                                   description='API.INVALID_RULE_ID')
230
231
        new_values = json.loads(raw_json)
232
        if 'name' not in new_values['data'].keys() or \
233
                not isinstance(new_values['data']['name'], str) or \
234
                len(str.strip(new_values['data']['name'])) == 0:
235
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
236
                                   description='API.INVALID_RULE_NAME')
237
        name = str.strip(new_values['data']['name'])
238
239
        if 'fdd_code' not in new_values['data'].keys() or \
240
                not isinstance(new_values['data']['fdd_code'], str) or \
241
                len(str.strip(new_values['data']['fdd_code'])) == 0:
242
            raise falcon.HTTPError(falcon.HTTP_400,
243
                                   title='API.BAD_REQUEST',
244
                                   description='API.INVALID_FDD_CODE')
245
        fdd_code = str.strip(new_values['data']['fdd_code'])
246
247
        if 'category' not in new_values['data'].keys() or \
248
                not isinstance(new_values['data']['category'], str) or \
249
                len(str.strip(new_values['data']['category'])) == 0 or \
250
                str.strip(new_values['data']['category']) not in \
251
                ('SYSTEM', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', 'COMBINEDEQUIPMENT'):
252
            raise falcon.HTTPError(falcon.HTTP_400,
253
                                   title='API.BAD_REQUEST',
254
                                   description='API.INVALID_CATEGORY')
255
        category = str.strip(new_values['data']['category'])
256
257
        if 'priority' not in new_values['data'].keys() or \
258
                not isinstance(new_values['data']['priority'], str) or \
259
                len(str.strip(new_values['data']['priority'])) == 0 or \
260
                str.strip(new_values['data']['priority']) not in \
261
                ('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'):
262
            raise falcon.HTTPError(falcon.HTTP_400,
263
                                   title='API.BAD_REQUEST',
264
                                   description='API.INVALID_PRIORITY')
265
        priority = str.strip(new_values['data']['priority'])
266
267
        if 'channel' not in new_values['data'].keys() or \
268
                not isinstance(new_values['data']['channel'], str) or \
269
                len(str.strip(new_values['data']['channel'])) == 0 or \
270
                str.strip(new_values['data']['channel']) not in ('WEB', 'EMAIL', 'SMS', 'WECHAT', 'CALL'):
271
            raise falcon.HTTPError(falcon.HTTP_400,
272
                                   title='API.BAD_REQUEST',
273
                                   description='API.INVALID_CHANNEL')
274
        channel = str.strip(new_values['data']['channel'])
275
276
        if 'expression' not in new_values['data'].keys() or \
277
                not isinstance(new_values['data']['expression'], str) or \
278
                len(str.strip(new_values['data']['expression'])) == 0:
279
            raise falcon.HTTPError(falcon.HTTP_400,
280
                                   title='API.BAD_REQUEST',
281
                                   description='API.INVALID_EXPRESSION')
282
        expression = str.strip(new_values['data']['expression'])
283
284
        if 'message_template' not in new_values['data'].keys() or \
285
                not isinstance(new_values['data']['message_template'], str) or \
286
                len(str.strip(new_values['data']['message_template'])) == 0:
287
            raise falcon.HTTPError(falcon.HTTP_400,
288
                                   title='API.BAD_REQUEST',
289
                                   description='API.INVALID_MESSAGE_TEMPLATE')
290
        message_template = str.strip(new_values['data']['message_template'])
291
292
        if 'is_enabled' not in new_values['data'].keys() or \
293
                not isinstance(new_values['data']['is_enabled'], bool):
294
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
295
                                   description='API.INVALID_IS_ENABLED')
296
        is_enabled = new_values['data']['is_enabled']
297
298
        cnx = mysql.connector.connect(**config.myems_fdd_db)
299
        cursor = cnx.cursor()
300
301
        cursor.execute(" SELECT id "
302
                       " FROM tbl_rules "
303
                       " WHERE id = %s ", (id_,))
304
        if cursor.fetchone() is None:
305
            cursor.close()
306
            cnx.disconnect()
307
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
308
                                   description='API.RULE_NOT_FOUND')
309
310
        cursor.execute(" SELECT name "
311
                       " FROM tbl_rules "
312
                       " WHERE name = %s AND id != %s ", (name, id_))
313
        if cursor.fetchone() is not None:
314
            cursor.close()
315
            cnx.disconnect()
316
            raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST',
317
                                   description='API.RULE_NAME_IS_ALREADY_IN_USE')
318
319
        update_row = (" UPDATE tbl_rules "
320
                      " SET name = %s, fdd_code = %s, category = %s, priority = %s, "
321
                      "     channel = %s, expression = %s, message_template = %s, "
322
                      "     is_enabled = %s "
323
                      " WHERE id = %s ")
324
        cursor.execute(update_row, (name,
325
                                    fdd_code,
326
                                    category,
327
                                    priority,
328
                                    channel,
329
                                    expression,
330
                                    message_template,
331
                                    is_enabled,
332
                                    id_,))
333
        cnx.commit()
334
335
        cursor.close()
336
        cnx.disconnect()
337
338
        resp.status = falcon.HTTP_200
339