Passed
Push — master ( c1feee...f28d3d )
by Guangyu
07:39 queued 12s
created

OfflineMeterFileCollection.on_post()   F

Complexity

Conditions 13

Size

Total Lines 97
Code Lines 68

Duplication

Lines 97
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 68
dl 97
loc 97
rs 3.9872
c 0
b 0
f 0
cc 13
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like core.offlinemeterfile.OfflineMeterFileCollection.on_post() 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
from datetime import datetime, timezone
7
import os
8
from core.userlogger import user_logger
9
10
11 View Code Duplication
class OfflineMeterFileCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
12
    @staticmethod
13
    def __init__():
14
        """"Initializes OfflineMeterFileCollection"""
15
        pass
16
17
    @staticmethod
18
    def on_options(req, resp):
19
        resp.status = falcon.HTTP_200
20
21
    @staticmethod
22
    def on_get(req, resp):
23
        cnx = mysql.connector.connect(**config.myems_historical_db)
24
        cursor = cnx.cursor()
25
26
        query = (" SELECT id, file_name, uuid, upload_datetime_utc, status "
27
                 " FROM tbl_offline_meter_files "
28
                 " ORDER BY upload_datetime_utc desc ")
29
        cursor.execute(query)
30
        rows = cursor.fetchall()
31
        cursor.close()
32
        cnx.disconnect()
33
34
        result = list()
35
        if rows is not None and len(rows) > 0:
36
            for row in rows:
37
                upload_datetime = row[3]
38
                upload_datetime = upload_datetime.replace(tzinfo=timezone.utc)
39
                meta_result = {"id": row[0],
40
                               "file_name": row[1],
41
                               "uuid": row[2],
42
                               "upload_datetime": upload_datetime.timestamp() * 1000,
43
                               "status": row[4]}
44
                result.append(meta_result)
45
46
        resp.body = json.dumps(result)
47
48
    @staticmethod
49
    @user_logger
50
    def on_post(req, resp):
51
        """Handles POST requests"""
52
        try:
53
            upload = req.get_param('file')
54
            # Read upload file as binary
55
            raw_blob = upload.file.read()
56
            # Retrieve filename
57
            filename = upload.filename
58
            file_uuid = str(uuid.uuid4())
59
60
            # Define file_path
61
            file_path = os.path.join(config.upload_path, file_uuid)
62
63
            # Write to a temporary file to prevent incomplete files from
64
            # being used.
65
            temp_file_path = file_path + '~'
66
67
            open(temp_file_path, 'wb').write(raw_blob)
68
69
            # Now that we know the file has been fully saved to disk
70
            # move it into place.
71
            os.rename(temp_file_path, file_path)
72
        except Exception as ex:
73
            raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR',
74
                                   description='API.FAILED_TO_UPLOAD_OFFLINE_METER_FILE')
75
76
        # Verify User Session
77
        token = req.headers.get('TOKEN')
78
        user_uuid = req.headers.get('USER-UUID')
79
        if token is None:
80
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
81
                                   description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
82
        if user_uuid is None:
83
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
84
                                   description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
85
86
        cnx = mysql.connector.connect(**config.myems_user_db)
87
        cursor = cnx.cursor()
88
89
        query = (" SELECT utc_expires "
90
                 " FROM tbl_sessions "
91
                 " WHERE user_uuid = %s AND token = %s")
92
        cursor.execute(query, (user_uuid, token,))
93
        row = cursor.fetchone()
94
95
        if row is None:
96
            if cursor:
97
                cursor.close()
98
            if cnx:
99
                cnx.disconnect()
100
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
101
                                   description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
102
        else:
103
            utc_expires = row[0]
104
            if datetime.utcnow() > utc_expires:
105
                if cursor:
106
                    cursor.close()
107
                if cnx:
108
                    cnx.disconnect()
109
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
110
                                       description='API.USER_SESSION_TIMEOUT')
111
112
        cursor.execute(" SELECT id "
113
                       " FROM tbl_users "
114
                       " WHERE uuid = %s ",
115
                       (user_uuid,))
116
        row = cursor.fetchone()
117
        if row is None:
118
            if cursor:
119
                cursor.close()
120
            if cnx:
121
                cnx.disconnect()
122
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
123
                                   description='API.INVALID_USER_PLEASE_RE_LOGIN')
124
        else:
125
            user_id = row[0]
126
127
        cnx = mysql.connector.connect(**config.myems_historical_db)
128
        cursor = cnx.cursor()
129
130
        add_values = (" INSERT INTO tbl_offline_meter_files "
131
                      " (file_name, uuid, upload_datetime_utc, status, file_object ) "
132
                      " VALUES (%s, %s, %s, %s, %s) ")
133
        cursor.execute(add_values, (filename,
134
                                    file_uuid,
135
                                    datetime.utcnow(),
136
                                    'new',
137
                                    raw_blob))
138
        new_id = cursor.lastrowid
139
        cnx.commit()
140
        cursor.close()
141
        cnx.disconnect()
142
143
        resp.status = falcon.HTTP_201
144
        resp.location = '/offlinemeterfiles/' + str(new_id)
145
146
147 View Code Duplication
class OfflineMeterFileItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
148
    @staticmethod
149
    def __init__():
150
        """"Initializes OfflineMeterFileItem"""
151
        pass
152
153
    @staticmethod
154
    def on_options(req, resp, id_):
155
        resp.status = falcon.HTTP_200
156
157
    @staticmethod
158
    def on_get(req, resp, id_):
159
        if not id_.isdigit() or int(id_) <= 0:
160
            raise falcon.HTTPError(falcon.HTTP_400,
161
                                   title='API.BAD_REQUEST',
162
                                   description='API.INVALID_OFFLINE_METER_FILE_ID')
163
164
        cnx = mysql.connector.connect(**config.myems_historical_db)
165
        cursor = cnx.cursor()
166
167
        query = (" SELECT id, file_name, uuid, upload_datetime_utc, status "
168
                 " FROM tbl_offline_meter_files "
169
                 " WHERE id = %s ")
170
        cursor.execute(query, (id_,))
171
        row = cursor.fetchone()
172
        cursor.close()
173
        cnx.disconnect()
174
        if row is None:
175
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
176
                                   description='API.OFFLINE_METER_FILE_NOT_FOUND')
177
178
        upload_datetime = row[3]
179
        upload_datetime = upload_datetime.replace(tzinfo=timezone.utc)
180
181
        result = {"id": row[0],
182
                  "file_name": row[1],
183
                  "uuid": row[2],
184
                  "upload_datetime": upload_datetime.timestamp() * 1000,
185
                  "status": row[4]}
186
        resp.body = json.dumps(result)
187
188
    @staticmethod
189
    @user_logger
190
    def on_delete(req, resp, id_):
191
        if not id_.isdigit() or int(id_) <= 0:
192
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
193
                                   description='API.INVALID_OFFLINE_METER_FILE_ID')
194
195
        cnx = mysql.connector.connect(**config.myems_historical_db)
196
        cursor = cnx.cursor()
197
198
        cursor.execute(" SELECT uuid "
199
                       " FROM tbl_offline_meter_files "
200
                       " WHERE id = %s ", (id_,))
201
        row = cursor.fetchone()
202
        if row is None:
203
            cursor.close()
204
            cnx.disconnect()
205
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
206
                                   description='API.OFFLINE_METER_FILE_NOT_FOUND')
207
208
        try:
209
            file_uuid = row[0]
210
            # Define file_path
211
            file_path = os.path.join(config.upload_path, file_uuid)
212
213
            # remove the file from disk
214
            os.remove(file_path)
215
        except Exception as ex:
216
            # ignore exception and don't return API.OFFLINE_METER_FILE_NOT_FOUND error
217
            pass
218
219
        # Note: the energy data imported from the deleted file will not be deleted
220
        cursor.execute(" DELETE FROM tbl_offline_meter_files WHERE id = %s ", (id_,))
221
        cnx.commit()
222
223
        cursor.close()
224
        cnx.disconnect()
225
226
        resp.status = falcon.HTTP_204
227
228
229 View Code Duplication
class OfflineMeterFileRestore:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
230
    @staticmethod
231
    def __init__():
232
        """"Initializes OfflineMeterFileRestore"""
233
        pass
234
235
    @staticmethod
236
    def on_options(req, resp, id_):
237
        resp.status = falcon.HTTP_200
238
239
    @staticmethod
240
    def on_get(req, resp, id_):
241
        if not id_.isdigit() or int(id_) <= 0:
242
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
243
                                   description='API.INVALID_OFFLINE_METER_FILE_ID')
244
245
        cnx = mysql.connector.connect(**config.myems_historical_db)
246
        cursor = cnx.cursor()
247
248
        query = (" SELECT uuid, file_object "
249
                 " FROM tbl_offline_meter_files "
250
                 " WHERE id = %s ")
251
        cursor.execute(query, (id_,))
252
        row = cursor.fetchone()
253
        cursor.close()
254
        cnx.disconnect()
255
256
        if row is None:
257
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
258
                                   description='API.OFFLINE_METER_FILE_NOT_FOUND')
259
260
        result = {"uuid": row[0],
261
                  "file_object": row[1]}
262
        try:
263
            raw_blob = result["file_object"]
264
            file_uuid = result["uuid"]
265
266
            # Define file_path
267
            file_path = os.path.join(config.upload_path, file_uuid)
268
269
            # Write to a temporary file to prevent incomplete files from
270
            # being used.
271
            temp_file_path = file_path + '~'
272
273
            open(temp_file_path, 'wb').write(raw_blob)
274
275
            # Now that we know the file has been fully saved to disk
276
            # move it into place.
277
            os.replace(temp_file_path, file_path)
278
        except Exception as ex:
279
            raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR',
280
                                   description='API.FAILED_TO_RESTORE_OFFLINE_METER_FILE')
281
        resp.body = json.dumps('success')
282