Passed
Push — master ( 90fdcc...086c6d )
by Guangyu
02:17 queued 11s
created

OfflineMeterFileCollection.on_post()   D

Complexity

Conditions 13

Size

Total Lines 96
Code Lines 67

Duplication

Lines 96
Ratio 100 %

Importance

Changes 0
Metric Value
cc 13
eloc 67
nop 2
dl 96
loc 96
rs 4.0199
c 0
b 0
f 0

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