cornflow 1.1.1a1__py3-none-any.whl → 1.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cornflow/app.py +0 -4
- cornflow/cli/utils.py +1 -1
- cornflow/config.py +2 -10
- cornflow/endpoints/__init__.py +0 -14
- cornflow/endpoints/execution.py +1 -1
- cornflow/endpoints/login.py +1 -8
- cornflow/models/__init__.py +0 -2
- cornflow/models/execution.py +0 -8
- cornflow/models/meta_models.py +12 -23
- cornflow/schemas/execution.py +0 -3
- cornflow/shared/const.py +0 -21
- cornflow/shared/exceptions.py +9 -20
- cornflow/tests/const.py +0 -7
- cornflow/tests/{custom_live_server.py → custom_liveServer.py} +1 -3
- cornflow/tests/custom_test_case.py +3 -2
- cornflow/tests/integration/test_commands.py +1 -1
- cornflow/tests/integration/test_cornflowclient.py +28 -116
- cornflow/tests/unit/test_alarms.py +9 -22
- cornflow/tests/unit/test_cli.py +5 -10
- cornflow/tests/unit/test_commands.py +2 -6
- cornflow/tests/unit/test_executions.py +0 -5
- cornflow/tests/unit/test_main_alarms.py +0 -8
- cornflow/tests/unit/test_users.py +2 -5
- {cornflow-1.1.1a1.dist-info → cornflow-1.1.4.dist-info}/METADATA +7 -7
- {cornflow-1.1.1a1.dist-info → cornflow-1.1.4.dist-info}/RECORD +28 -35
- {cornflow-1.1.1a1.dist-info → cornflow-1.1.4.dist-info}/WHEEL +1 -1
- cornflow/endpoints/reports.py +0 -283
- cornflow/migrations/versions/83164be03c23_.py +0 -40
- cornflow/migrations/versions/96f00d0961d1_reports_table.py +0 -50
- cornflow/models/reports.py +0 -119
- cornflow/schemas/reports.py +0 -48
- cornflow/static/v1.json +0 -3854
- cornflow/tests/unit/test_reports.py +0 -308
- {cornflow-1.1.1a1.dist-info → cornflow-1.1.4.dist-info}/entry_points.txt +0 -0
- {cornflow-1.1.1a1.dist-info → cornflow-1.1.4.dist-info}/top_level.txt +0 -0
cornflow/endpoints/reports.py
DELETED
@@ -1,283 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
External endpoints to manage the reports: create new ones, list all of them, get one in particular
|
3
|
-
These endpoints have different access url, but manage the same data entities
|
4
|
-
"""
|
5
|
-
import os
|
6
|
-
|
7
|
-
from flask import current_app, request, send_from_directory
|
8
|
-
from flask_apispec import marshal_with, use_kwargs, doc
|
9
|
-
from werkzeug.utils import secure_filename
|
10
|
-
import uuid
|
11
|
-
|
12
|
-
from cornflow.endpoints.meta_resource import BaseMetaResource
|
13
|
-
from cornflow.models import ExecutionModel, ReportModel
|
14
|
-
from cornflow.schemas.reports import (
|
15
|
-
ReportSchema,
|
16
|
-
ReportEditRequest,
|
17
|
-
QueryFiltersReports,
|
18
|
-
ReportRequest,
|
19
|
-
)
|
20
|
-
from cornflow.shared.authentication import Auth, authenticate
|
21
|
-
from cornflow.shared.const import SERVICE_ROLE
|
22
|
-
from cornflow.shared.exceptions import (
|
23
|
-
FileError,
|
24
|
-
ObjectDoesNotExist,
|
25
|
-
NoPermission,
|
26
|
-
)
|
27
|
-
|
28
|
-
|
29
|
-
class ReportEndpoint(BaseMetaResource):
|
30
|
-
"""
|
31
|
-
Endpoint used to create a new report or get all the reports and their information back
|
32
|
-
"""
|
33
|
-
|
34
|
-
ROLES_WITH_ACCESS = [SERVICE_ROLE]
|
35
|
-
|
36
|
-
def __init__(self):
|
37
|
-
super().__init__()
|
38
|
-
self.model = ReportModel
|
39
|
-
self.data_model = ReportModel
|
40
|
-
self.foreign_data = {"execution_id": ExecutionModel}
|
41
|
-
|
42
|
-
@doc(description="Get all reports", tags=["Reports"])
|
43
|
-
@authenticate(auth_class=Auth())
|
44
|
-
@marshal_with(ReportSchema(many=True))
|
45
|
-
@use_kwargs(QueryFiltersReports, location="query")
|
46
|
-
def get(self, **kwargs):
|
47
|
-
"""
|
48
|
-
API method to get all the reports created by the user and its related info
|
49
|
-
It requires authentication to be passed in the form of a token that has to be linked to
|
50
|
-
an existing session (login) made by a user
|
51
|
-
|
52
|
-
:return: A dictionary with a message (error if authentication failed or a list with all the reports
|
53
|
-
created by the authenticated user) and a integer with the HTTP status code
|
54
|
-
:rtype: Tuple(dict, integer)
|
55
|
-
"""
|
56
|
-
reports = self.get_list(user=self.get_user(), **kwargs)
|
57
|
-
current_app.logger.info(f"User {self.get_user()} gets list of reports")
|
58
|
-
return reports
|
59
|
-
|
60
|
-
@doc(description="Create a report", tags=["Reports"])
|
61
|
-
@authenticate(auth_class=Auth())
|
62
|
-
@use_kwargs(ReportRequest, location="form")
|
63
|
-
@marshal_with(ReportSchema)
|
64
|
-
def post(self, **kwargs):
|
65
|
-
"""
|
66
|
-
API method to create a new report linked to an existing execution
|
67
|
-
It requires authentication to be passed in the form of a token that has to be linked to
|
68
|
-
an existing session (login) made by a user
|
69
|
-
|
70
|
-
:return: A dictionary with a message (error if authentication failed, error if data is not validated or
|
71
|
-
the reference_id for the newly created report if successful) and a integer with the HTTP status code
|
72
|
-
:rtype: Tuple(dict, integer)
|
73
|
-
"""
|
74
|
-
|
75
|
-
execution = ExecutionModel.get_one_object(idx=kwargs["execution_id"])
|
76
|
-
|
77
|
-
if execution is None:
|
78
|
-
raise ObjectDoesNotExist("The execution does not exist")
|
79
|
-
if "file" not in request.files:
|
80
|
-
# we're creating an empty report.
|
81
|
-
# which is possible
|
82
|
-
report = ReportModel(get_report_info(kwargs, execution, None))
|
83
|
-
|
84
|
-
report.save()
|
85
|
-
return report, 201
|
86
|
-
|
87
|
-
file = request.files["file"]
|
88
|
-
report_name = new_file_name(file)
|
89
|
-
|
90
|
-
report = ReportModel(get_report_info(kwargs, execution, report_name))
|
91
|
-
|
92
|
-
report.save()
|
93
|
-
|
94
|
-
# We try to save the file, if an error is raised then we delete the record on the database
|
95
|
-
try:
|
96
|
-
write_file(file, execution.id, report_name)
|
97
|
-
return report, 201
|
98
|
-
|
99
|
-
except Exception as error:
|
100
|
-
report.delete()
|
101
|
-
current_app.logger.error(error)
|
102
|
-
raise FileError(error=str(error))
|
103
|
-
|
104
|
-
|
105
|
-
class ReportDetailsEndpointBase(BaseMetaResource):
|
106
|
-
"""
|
107
|
-
Endpoint used to get the information of a certain report. But not the data!
|
108
|
-
"""
|
109
|
-
|
110
|
-
def __init__(self):
|
111
|
-
super().__init__()
|
112
|
-
self.data_model = ReportModel
|
113
|
-
self.foreign_data = {"execution_id": ExecutionModel}
|
114
|
-
|
115
|
-
|
116
|
-
class ReportDetailsEditEndpoint(ReportDetailsEndpointBase):
|
117
|
-
|
118
|
-
ROLES_WITH_ACCESS = [SERVICE_ROLE]
|
119
|
-
|
120
|
-
@doc(description="Edit a report", tags=["Reports"], inherit=False)
|
121
|
-
@authenticate(auth_class=Auth())
|
122
|
-
@use_kwargs(ReportEditRequest, location="form")
|
123
|
-
def put(self, idx, **data):
|
124
|
-
"""
|
125
|
-
Edit an existing report
|
126
|
-
|
127
|
-
:param string idx: ID of the report.
|
128
|
-
:return: A dictionary with a message (error if authentication failed, or the report does not exist or
|
129
|
-
a message) and an integer with the HTTP status code.
|
130
|
-
:rtype: Tuple(dict, integer)
|
131
|
-
"""
|
132
|
-
# TODO: forbid non-service users from running put
|
133
|
-
current_app.logger.info(f"User {self.get_user()} edits report {idx}")
|
134
|
-
|
135
|
-
report = self.get_detail(idx=idx)
|
136
|
-
|
137
|
-
if "file" not in request.files:
|
138
|
-
# we're creating an empty report.
|
139
|
-
# which is possible
|
140
|
-
report.update(data)
|
141
|
-
report.save()
|
142
|
-
return {"message": "Updated correctly"}, 200
|
143
|
-
|
144
|
-
# there's two cases,
|
145
|
-
# (1) the report already has a file
|
146
|
-
# (2) the report doesn't yet have a file
|
147
|
-
file = request.files["file"]
|
148
|
-
report_name = new_file_name(file)
|
149
|
-
old_name = report.file_url
|
150
|
-
# we update the report with the new content, including the new name
|
151
|
-
report.update(dict(**data, file_url=report_name))
|
152
|
-
|
153
|
-
# We try to save the file, if an error is raised then we delete the record on the database
|
154
|
-
try:
|
155
|
-
write_file(file, report.execution_id, report_name)
|
156
|
-
report.save()
|
157
|
-
|
158
|
-
except Exception as error:
|
159
|
-
# we do not save the report
|
160
|
-
current_app.logger.error(error)
|
161
|
-
raise FileError(error=str(error))
|
162
|
-
|
163
|
-
# if it saves correctly, we delete the old file, if exists
|
164
|
-
# if unsuccessful, we still return 201 but log the error
|
165
|
-
if old_name is not None:
|
166
|
-
try:
|
167
|
-
os.remove(get_report_path(report))
|
168
|
-
except OSError as error:
|
169
|
-
current_app.logger.error(error)
|
170
|
-
return {"message": "Updated correctly"}, 200
|
171
|
-
|
172
|
-
|
173
|
-
class ReportDetailsEndpoint(ReportDetailsEndpointBase):
|
174
|
-
@doc(description="Get details of a report", tags=["Reports"], inherit=False)
|
175
|
-
@authenticate(auth_class=Auth())
|
176
|
-
@marshal_with(ReportSchema)
|
177
|
-
@BaseMetaResource.get_data_or_404
|
178
|
-
def get(self, idx):
|
179
|
-
"""
|
180
|
-
API method to get a report created by the user and its related info.
|
181
|
-
It requires authentication to be passed in the form of a token that has to be linked to
|
182
|
-
an existing session (login) made by a user.
|
183
|
-
|
184
|
-
:param str idx: ID of the report.
|
185
|
-
:return: A dictionary with a message (error if authentication failed, or the report does not exist or
|
186
|
-
the data of the report) and an integer with the HTTP status code.
|
187
|
-
:rtype: Tuple(dict, integer)
|
188
|
-
"""
|
189
|
-
# TODO: are we able to download the name in the database and not as part of the file?
|
190
|
-
current_app.logger.info(f"User {self.get_user()} gets details of report {idx}")
|
191
|
-
report = self.get_detail(user=self.get_user(), idx=idx)
|
192
|
-
|
193
|
-
if report is None:
|
194
|
-
raise ObjectDoesNotExist
|
195
|
-
|
196
|
-
# if there's no file, we do not return it:
|
197
|
-
if report.file_url is None:
|
198
|
-
return report, 200
|
199
|
-
|
200
|
-
my_dir = get_report_dir(report.execution_id)
|
201
|
-
response = send_from_directory(my_dir, report.file_url)
|
202
|
-
response.headers["File-Description"] = report.description
|
203
|
-
response.headers["File-Name"] = report.file_url
|
204
|
-
return response
|
205
|
-
|
206
|
-
@doc(description="Delete a report", tags=["Reports"], inherit=False)
|
207
|
-
@authenticate(auth_class=Auth())
|
208
|
-
def delete(self, idx):
|
209
|
-
"""
|
210
|
-
API method to delete a report created by the user and its related info.
|
211
|
-
It requires authentication to be passed in the form of a token that has to be linked to
|
212
|
-
an existing session (login) made by a user.
|
213
|
-
|
214
|
-
:param string idx: ID of the report.
|
215
|
-
:return: A dictionary with a message (error if authentication failed, or the report does not exist or
|
216
|
-
a message) and an integer with the HTTP status code.
|
217
|
-
:rtype: Tuple(dict, integer)
|
218
|
-
"""
|
219
|
-
|
220
|
-
# get report objet
|
221
|
-
report = self.get_detail(user_id=self.get_user_id(), idx=idx)
|
222
|
-
|
223
|
-
if report is None:
|
224
|
-
raise ObjectDoesNotExist
|
225
|
-
|
226
|
-
# delete file
|
227
|
-
os.remove(get_report_path(report))
|
228
|
-
|
229
|
-
return self.delete_detail(user_id=self.get_user_id(), idx=idx)
|
230
|
-
|
231
|
-
|
232
|
-
def get_report_dir(execution_id):
|
233
|
-
return f"{current_app.config['UPLOAD_FOLDER']}/{execution_id}"
|
234
|
-
|
235
|
-
|
236
|
-
def get_report_path(report):
|
237
|
-
try:
|
238
|
-
return f"{get_report_dir(report['execution_id'])}/{report['file_url']}"
|
239
|
-
except:
|
240
|
-
return f"{get_report_dir(report.execution_id)}/{report.file_url}"
|
241
|
-
|
242
|
-
|
243
|
-
def new_file_name(file):
|
244
|
-
|
245
|
-
filename = secure_filename(file.filename)
|
246
|
-
filename_extension = filename.split(".")[-1]
|
247
|
-
|
248
|
-
if filename_extension not in current_app.config["ALLOWED_EXTENSIONS"]:
|
249
|
-
return {
|
250
|
-
"message": f"Invalid file extension. "
|
251
|
-
f"Valid extensions are: {current_app.config['ALLOWED_EXTENSIONS']}"
|
252
|
-
}, 400
|
253
|
-
|
254
|
-
report_name = f"{uuid.uuid4().hex}.{filename_extension}"
|
255
|
-
|
256
|
-
return report_name
|
257
|
-
|
258
|
-
|
259
|
-
def write_file(file, execution_id, file_name):
|
260
|
-
my_directory = get_report_dir(execution_id)
|
261
|
-
|
262
|
-
# we create a directory for the execution
|
263
|
-
if not os.path.exists(my_directory):
|
264
|
-
current_app.logger.info(f"Creating directory {my_directory}")
|
265
|
-
os.mkdir(my_directory)
|
266
|
-
|
267
|
-
save_path = os.path.normpath(os.path.join(my_directory, file_name))
|
268
|
-
|
269
|
-
if "static" not in save_path or ".." in save_path:
|
270
|
-
raise NoPermission("Invalid file name")
|
271
|
-
file.save(save_path)
|
272
|
-
|
273
|
-
|
274
|
-
def get_report_info(data, execution, file_url=None):
|
275
|
-
return {
|
276
|
-
"name": data["name"],
|
277
|
-
"file_url": file_url,
|
278
|
-
"execution_id": execution.id,
|
279
|
-
"user_id": execution.user_id,
|
280
|
-
"description": data.get("description", ""),
|
281
|
-
"state": data.get("state"),
|
282
|
-
"state_message": data.get("state_message"),
|
283
|
-
}
|
@@ -1,40 +0,0 @@
|
|
1
|
-
"""empty message
|
2
|
-
|
3
|
-
Revision ID: 83164be03c23
|
4
|
-
Revises: 96f00d0961d1
|
5
|
-
Create Date: 2024-07-23 13:18:47.748324
|
6
|
-
|
7
|
-
"""
|
8
|
-
from alembic import op
|
9
|
-
import sqlalchemy as sa
|
10
|
-
|
11
|
-
|
12
|
-
# revision identifiers, used by Alembic.
|
13
|
-
revision = '83164be03c23'
|
14
|
-
down_revision = '96f00d0961d1'
|
15
|
-
branch_labels = None
|
16
|
-
depends_on = None
|
17
|
-
|
18
|
-
|
19
|
-
def upgrade():
|
20
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
21
|
-
with op.batch_alter_table('reports', schema=None) as batch_op:
|
22
|
-
batch_op.add_column(sa.Column('state', sa.SmallInteger(), nullable=True))
|
23
|
-
batch_op.add_column(sa.Column('state_message', sa.TEXT(), nullable=True))
|
24
|
-
batch_op.alter_column('file_url',
|
25
|
-
existing_type=sa.VARCHAR(length=256),
|
26
|
-
nullable=True)
|
27
|
-
|
28
|
-
# ### end Alembic commands ###
|
29
|
-
|
30
|
-
|
31
|
-
def downgrade():
|
32
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
33
|
-
with op.batch_alter_table('reports', schema=None) as batch_op:
|
34
|
-
batch_op.alter_column('file_url',
|
35
|
-
existing_type=sa.VARCHAR(length=256),
|
36
|
-
nullable=False)
|
37
|
-
batch_op.drop_column('state_message')
|
38
|
-
batch_op.drop_column('state')
|
39
|
-
|
40
|
-
# ### end Alembic commands ###
|
@@ -1,50 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Adds reports table to database
|
3
|
-
|
4
|
-
Revision ID: 96f00d0961d1
|
5
|
-
Revises: 991b98e24225
|
6
|
-
Create Date: 2024-06-12 18:47:06.366487
|
7
|
-
|
8
|
-
"""
|
9
|
-
|
10
|
-
from alembic import op
|
11
|
-
import sqlalchemy as sa
|
12
|
-
|
13
|
-
|
14
|
-
# revision identifiers, used by Alembic.
|
15
|
-
revision = "96f00d0961d1"
|
16
|
-
down_revision = "991b98e24225"
|
17
|
-
branch_labels = None
|
18
|
-
depends_on = None
|
19
|
-
|
20
|
-
|
21
|
-
def upgrade():
|
22
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
23
|
-
op.create_table(
|
24
|
-
"reports",
|
25
|
-
sa.Column("created_at", sa.DateTime(), nullable=False),
|
26
|
-
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
27
|
-
sa.Column("deleted_at", sa.DateTime(), nullable=True),
|
28
|
-
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
29
|
-
sa.Column("execution_id", sa.String(length=256), nullable=False),
|
30
|
-
sa.Column("name", sa.String(length=256), nullable=False),
|
31
|
-
sa.Column("description", sa.TEXT(), nullable=True),
|
32
|
-
sa.Column("file_url", sa.String(length=256), nullable=False),
|
33
|
-
sa.Column("user_id", sa.Integer(), nullable=False),
|
34
|
-
sa.ForeignKeyConstraint(
|
35
|
-
["execution_id"],
|
36
|
-
["executions.id"],
|
37
|
-
),
|
38
|
-
sa.ForeignKeyConstraint(
|
39
|
-
["user_id"],
|
40
|
-
["users.id"],
|
41
|
-
),
|
42
|
-
sa.PrimaryKeyConstraint("id"),
|
43
|
-
)
|
44
|
-
# ### end Alembic commands ###
|
45
|
-
|
46
|
-
|
47
|
-
def downgrade():
|
48
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
49
|
-
op.drop_table("reports")
|
50
|
-
# ### end Alembic commands ###
|
cornflow/models/reports.py
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Model for the reports
|
3
|
-
"""
|
4
|
-
|
5
|
-
# Import from libraries
|
6
|
-
from sqlalchemy.dialects.postgresql import TEXT
|
7
|
-
from sqlalchemy.ext.declarative import declared_attr
|
8
|
-
|
9
|
-
# Imports from internal modules
|
10
|
-
from cornflow.models.base_data_model import TraceAttributesModel
|
11
|
-
from cornflow.shared import db
|
12
|
-
from cornflow.shared.const import REPORT_STATE, REPORT_STATE_MSG
|
13
|
-
|
14
|
-
|
15
|
-
class ReportModel(TraceAttributesModel):
|
16
|
-
"""
|
17
|
-
Model class for the Reports.
|
18
|
-
It inherits from :class:`TraceAttributesModel<cornflow.models.base_data_model.TraceAttributesModel>` to have the trace fields and user field.
|
19
|
-
|
20
|
-
- **id**: int, the report id, primary key for the reports.
|
21
|
-
- **execution_id**: str, the foreign key for the execution (:class:`ExecutionModel`). It links the report to its
|
22
|
-
parent execution.
|
23
|
-
- **file_url**: str, the link with the actual report. It should be a valid url to a cloud storage bucket or a file.
|
24
|
-
- **name**: str, the name of the report given by the user.
|
25
|
-
- **description**: str, the description of the report given by the user. It is optional.
|
26
|
-
- **user_id**: int, the foreign key for the user (:class:`UserModel`). It links the report to its owner.
|
27
|
-
- **created_at**: datetime, the datetime when the report was created (in UTC).
|
28
|
-
This datetime is generated automatically, the user does not need to provide it.
|
29
|
-
- **updated_at**: datetime, the datetime when the report was last updated (in UTC).
|
30
|
-
This datetime is generated automatically, the user does not need to provide it.
|
31
|
-
- **deleted_at**: datetime, the datetime when the report was deleted (in UTC). Even though it is deleted,
|
32
|
-
actually, it is not deleted from the database, in order to have a command that cleans up deleted data
|
33
|
-
after a certain time of its deletion.
|
34
|
-
This datetime is generated automatically, the user does not need to provide it.
|
35
|
-
|
36
|
-
"""
|
37
|
-
|
38
|
-
# Table name in the database
|
39
|
-
__tablename__ = "reports"
|
40
|
-
|
41
|
-
# Model fields
|
42
|
-
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
43
|
-
execution_id = db.Column(
|
44
|
-
db.String(256), db.ForeignKey("executions.id"), nullable=False
|
45
|
-
)
|
46
|
-
name = db.Column(db.String(256), nullable=False)
|
47
|
-
description = db.Column(TEXT, nullable=True)
|
48
|
-
file_url = db.Column(db.String(256), nullable=True)
|
49
|
-
state = db.Column(db.SmallInteger, default=REPORT_STATE.CORRECT)
|
50
|
-
state_message = db.Column(TEXT, default=REPORT_STATE_MSG[REPORT_STATE.CORRECT])
|
51
|
-
|
52
|
-
@declared_attr
|
53
|
-
def user_id(self):
|
54
|
-
"""
|
55
|
-
The foreign key for the user (:class:`UserModel<cornflow.models.UserModel>`).
|
56
|
-
"""
|
57
|
-
return db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
|
58
|
-
|
59
|
-
@declared_attr
|
60
|
-
def user(self):
|
61
|
-
return db.relationship("UserModel")
|
62
|
-
|
63
|
-
def __init__(self, data: dict):
|
64
|
-
super().__init__()
|
65
|
-
self.user_id = data.get("user_id")
|
66
|
-
self.execution_id = data.get("execution_id")
|
67
|
-
self.name = data.get("name")
|
68
|
-
self.description = data.get("description")
|
69
|
-
self.file_url = data.get("file_url")
|
70
|
-
self.state = data.get("state")
|
71
|
-
if self.state is None:
|
72
|
-
if self.file_url is None:
|
73
|
-
self.state = REPORT_STATE.UNKNOWN
|
74
|
-
else:
|
75
|
-
self.state = REPORT_STATE.CORRECT
|
76
|
-
self.state_message = data.get("state_message")
|
77
|
-
if self.state_message is None:
|
78
|
-
self.state_message = REPORT_STATE_MSG.get(self.state)
|
79
|
-
|
80
|
-
def update(self, data):
|
81
|
-
"""
|
82
|
-
Method used to update a report from the database
|
83
|
-
|
84
|
-
:param dict data: the data of the object
|
85
|
-
:return: None
|
86
|
-
:rtype: None
|
87
|
-
"""
|
88
|
-
# we try to keep the state_message synced, by default
|
89
|
-
if "state" in data and "state_message" not in data:
|
90
|
-
data["state_message"] = REPORT_STATE_MSG[data["state"]]
|
91
|
-
super().update(data)
|
92
|
-
|
93
|
-
def update_link(self, file_url: str):
|
94
|
-
"""
|
95
|
-
Method to update the report link
|
96
|
-
|
97
|
-
:param str file_url: new URL for the report
|
98
|
-
:return: nothing
|
99
|
-
"""
|
100
|
-
self.file_url = file_url
|
101
|
-
super().update({})
|
102
|
-
|
103
|
-
def __repr__(self):
|
104
|
-
"""
|
105
|
-
Method to represent the class :class:`ReportModel`
|
106
|
-
|
107
|
-
:return: The representation of the :class:`ReportModel`
|
108
|
-
:rtype: str
|
109
|
-
"""
|
110
|
-
return f"<Report {self.id}>"
|
111
|
-
|
112
|
-
def __str__(self):
|
113
|
-
"""
|
114
|
-
Method to print a string representation of the :class:`ReportModel`
|
115
|
-
|
116
|
-
:return: The string for the :class:`ReportModel`
|
117
|
-
:rtype: str
|
118
|
-
"""
|
119
|
-
return self.__repr__()
|
cornflow/schemas/reports.py
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# Imports from libraries
|
2
|
-
from marshmallow import fields, Schema, INCLUDE
|
3
|
-
|
4
|
-
# Imports from internal modules
|
5
|
-
from .common import BaseQueryFilters
|
6
|
-
|
7
|
-
|
8
|
-
class QueryFiltersReports(BaseQueryFilters):
|
9
|
-
execution_id = fields.Str(required=False)
|
10
|
-
|
11
|
-
|
12
|
-
class ReportSchemaBase(Schema):
|
13
|
-
id = fields.Int(dump_only=True)
|
14
|
-
file_url = fields.Str(required=False)
|
15
|
-
name = fields.Str(required=True)
|
16
|
-
state = fields.Int()
|
17
|
-
|
18
|
-
|
19
|
-
class ReportSchema(ReportSchemaBase):
|
20
|
-
user_id = fields.Int(required=False, load_only=True)
|
21
|
-
execution_id = fields.Str(required=True)
|
22
|
-
description = fields.Str()
|
23
|
-
state_message = fields.Str()
|
24
|
-
created_at = fields.DateTime(dump_only=True)
|
25
|
-
updated_at = fields.DateTime(dump_only=True)
|
26
|
-
deleted_at = fields.DateTime(dump_only=True)
|
27
|
-
|
28
|
-
|
29
|
-
class ReportEditRequest(Schema):
|
30
|
-
class META:
|
31
|
-
unknown = INCLUDE
|
32
|
-
|
33
|
-
name = fields.Str()
|
34
|
-
description = fields.Str()
|
35
|
-
file_url = fields.Str(required=False)
|
36
|
-
state = fields.Int()
|
37
|
-
state_message = fields.Str()
|
38
|
-
|
39
|
-
|
40
|
-
class ReportRequest(Schema):
|
41
|
-
class META:
|
42
|
-
unknown = INCLUDE
|
43
|
-
|
44
|
-
name = fields.Str(required=True)
|
45
|
-
description = fields.Str(required=False)
|
46
|
-
execution_id = fields.Str(required=True)
|
47
|
-
state = fields.Int()
|
48
|
-
state_message = fields.Str()
|