cornflow 1.1.0a1__py3-none-any.whl → 1.1.1a1__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.
Files changed (38) hide show
  1. cornflow/app.py +4 -0
  2. cornflow/cli/utils.py +1 -1
  3. cornflow/config.py +10 -2
  4. cornflow/endpoints/__init__.py +28 -19
  5. cornflow/endpoints/example_data.py +64 -13
  6. cornflow/endpoints/execution.py +1 -1
  7. cornflow/endpoints/login.py +26 -6
  8. cornflow/endpoints/reports.py +283 -0
  9. cornflow/migrations/versions/83164be03c23_.py +40 -0
  10. cornflow/migrations/versions/96f00d0961d1_reports_table.py +50 -0
  11. cornflow/models/__init__.py +2 -0
  12. cornflow/models/execution.py +8 -0
  13. cornflow/models/meta_models.py +23 -12
  14. cornflow/models/reports.py +119 -0
  15. cornflow/schemas/example_data.py +7 -2
  16. cornflow/schemas/execution.py +3 -0
  17. cornflow/schemas/reports.py +48 -0
  18. cornflow/shared/const.py +21 -0
  19. cornflow/shared/exceptions.py +20 -9
  20. cornflow/static/v1.json +3854 -0
  21. cornflow/tests/const.py +7 -0
  22. cornflow/tests/{custom_liveServer.py → custom_live_server.py} +3 -1
  23. cornflow/tests/custom_test_case.py +2 -3
  24. cornflow/tests/integration/test_commands.py +1 -1
  25. cornflow/tests/integration/test_cornflowclient.py +116 -28
  26. cornflow/tests/unit/test_alarms.py +22 -9
  27. cornflow/tests/unit/test_cli.py +10 -5
  28. cornflow/tests/unit/test_commands.py +6 -2
  29. cornflow/tests/unit/test_example_data.py +83 -13
  30. cornflow/tests/unit/test_executions.py +5 -0
  31. cornflow/tests/unit/test_main_alarms.py +8 -0
  32. cornflow/tests/unit/test_reports.py +308 -0
  33. cornflow/tests/unit/test_users.py +5 -2
  34. {cornflow-1.1.0a1.dist-info → cornflow-1.1.1a1.dist-info}/METADATA +31 -31
  35. {cornflow-1.1.0a1.dist-info → cornflow-1.1.1a1.dist-info}/RECORD +38 -31
  36. {cornflow-1.1.0a1.dist-info → cornflow-1.1.1a1.dist-info}/WHEEL +1 -1
  37. {cornflow-1.1.0a1.dist-info → cornflow-1.1.1a1.dist-info}/entry_points.txt +0 -0
  38. {cornflow-1.1.0a1.dist-info → cornflow-1.1.1a1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,308 @@
1
+ """
2
+ Unit test for the reports endpoints
3
+ """
4
+
5
+ import shutil
6
+ import os
7
+ import json
8
+
9
+ from flask import current_app
10
+
11
+ from cornflow.models import ReportModel, InstanceModel, ExecutionModel
12
+ from cornflow.endpoints.reports import get_report_path
13
+ from cornflow.tests.const import (
14
+ INSTANCE_PATH,
15
+ REPORT_PATH,
16
+ REPORT_HTML_FILE_PATH,
17
+ REPORT_URL,
18
+ INSTANCE_URL,
19
+ EXECUTION_PATH,
20
+ EXECUTION_URL_NORUN,
21
+ REPORT_PDF_FILE_PATH,
22
+ )
23
+ from cornflow.tests.custom_test_case import CustomTestCase
24
+
25
+
26
+ class TestReportsListEndpoint(CustomTestCase):
27
+ def setUp(self):
28
+ # we create an instance, and an execution
29
+ super().setUp()
30
+
31
+ self.service_token = self.create_service_user()
32
+
33
+ # instance:
34
+ with open(INSTANCE_PATH) as f:
35
+ payload = json.load(f)
36
+ fk_id = self.create_new_row(INSTANCE_URL, InstanceModel, payload)
37
+
38
+ def load_file_fk(_file, **kwargs):
39
+ with open(_file) as f:
40
+ temp = json.load(f)
41
+ temp.update(kwargs)
42
+ return temp
43
+
44
+ # execution:
45
+ fk_id = self.create_new_row(
46
+ EXECUTION_URL_NORUN,
47
+ ExecutionModel,
48
+ payload=load_file_fk(EXECUTION_PATH, instance_id=fk_id),
49
+ )
50
+
51
+ self.payload = load_file_fk(REPORT_PATH, execution_id=fk_id)
52
+
53
+ self.url = REPORT_URL
54
+ self.model = ReportModel
55
+
56
+ self.keys_to_check = [
57
+ "id",
58
+ "file_url",
59
+ "name",
60
+ "execution_id",
61
+ "description",
62
+ "created_at",
63
+ "updated_at",
64
+ "deleted_at",
65
+ ]
66
+
67
+ def tearDown(self):
68
+ super().tearDown()
69
+ my_directories = os.listdir(current_app.config["UPLOAD_FOLDER"])
70
+ for _dir in my_directories:
71
+ try:
72
+ shutil.rmtree(os.path.join(current_app.config["UPLOAD_FOLDER"], _dir))
73
+ except OSError:
74
+ pass
75
+
76
+ def test_new_report_html(self):
77
+ with open(REPORT_HTML_FILE_PATH, "rb") as _file:
78
+ response = self.client.post(
79
+ self.url,
80
+ data=dict(file=_file, **self.payload),
81
+ follow_redirects=True,
82
+ headers=self.get_header_with_auth(
83
+ self.service_token, content_type="multipart/form-data"
84
+ ),
85
+ )
86
+
87
+ self.assertEqual(201, response.status_code)
88
+
89
+ for key in self.keys_to_check:
90
+ self.assertTrue(key in response.json)
91
+
92
+ for key, value in self.payload.items():
93
+ self.assertEqual(response.json[key], value)
94
+
95
+ # check that the file in the test folder and the one generated on the static fodler are equal
96
+ with open(REPORT_HTML_FILE_PATH, "rb") as f:
97
+ file = f.read()
98
+
99
+ my_upload_path = get_report_path(response.json)
100
+
101
+ with open(my_upload_path, "rb") as f:
102
+ file2 = f.read()
103
+
104
+ self.assertEqual(file, file2)
105
+ return response.json
106
+
107
+ def test_new_report_empty(self):
108
+ response = self.client.post(
109
+ self.url,
110
+ data=dict(**self.payload),
111
+ follow_redirects=True,
112
+ headers=self.get_header_with_auth(
113
+ self.service_token, content_type="multipart/form-data"
114
+ ),
115
+ )
116
+
117
+ self.assertEqual(201, response.status_code)
118
+
119
+ for key in self.keys_to_check:
120
+ self.assertTrue(key in response.json)
121
+
122
+ for key, value in self.payload.items():
123
+ self.assertEqual(response.json[key], value)
124
+
125
+ # check that we did not save any file
126
+ my_upload_path = (
127
+ f"{current_app.config['UPLOAD_FOLDER']}/"
128
+ f"{self.payload['execution_id']}/{self.payload['name']}.html"
129
+ )
130
+ self.assertFalse(os.path.exists(my_upload_path))
131
+
132
+ return response.json
133
+
134
+ def test_new_report_pdf(self):
135
+ response = self.client.post(
136
+ self.url,
137
+ data=dict(file=(open(REPORT_PDF_FILE_PATH, "rb")), **self.payload),
138
+ follow_redirects=True,
139
+ headers=self.get_header_with_auth(
140
+ self.service_token, content_type="multipart/form-data"
141
+ ),
142
+ )
143
+
144
+ self.assertEqual(201, response.status_code)
145
+
146
+ for key in self.keys_to_check:
147
+ self.assertTrue(key in response.json)
148
+
149
+ for key, value in self.payload.items():
150
+ self.assertEqual(response.json[key], value)
151
+
152
+ # check that the file in the test folder and the one generated on the static fodler are equal
153
+ with open(REPORT_PDF_FILE_PATH, "rb") as f:
154
+ file = f.read()
155
+
156
+ my_upload_path = get_report_path(response.json)
157
+ with open(my_upload_path, "rb") as f:
158
+ file2 = f.read()
159
+
160
+ self.assertEqual(file, file2)
161
+ return response.json
162
+
163
+ def test_new_report_not_allowed(self):
164
+ with open(REPORT_HTML_FILE_PATH, "rb") as _file:
165
+ response = self.client.post(
166
+ self.url,
167
+ data=dict(file=_file, **self.payload),
168
+ follow_redirects=True,
169
+ headers=self.get_header_with_auth(
170
+ self.token, content_type="multipart/form-data"
171
+ ),
172
+ )
173
+
174
+ self.assertEqual(response.status_code, 403)
175
+
176
+ def test_edit_report_not_allowed(self):
177
+ item = self.test_new_report_html()
178
+ payload = dict(name="new name2")
179
+ response = self.client.put(
180
+ f"{self.url}{item['id']}/edit/",
181
+ data=payload,
182
+ follow_redirects=True,
183
+ headers=self.get_header_with_auth(
184
+ self.token, content_type="multipart/form-data"
185
+ ),
186
+ )
187
+
188
+ self.assertEqual(response.status_code, 403)
189
+
190
+ def test_new_report_no_execution(self):
191
+ payload = dict(self.payload)
192
+ payload["execution_id"] = "bad_id"
193
+ response = self.client.post(
194
+ self.url,
195
+ data=dict(file=(open(REPORT_HTML_FILE_PATH, "rb")), **payload),
196
+ follow_redirects=True,
197
+ headers=self.get_header_with_auth(
198
+ self.service_token, content_type="multipart/form-data"
199
+ ),
200
+ )
201
+
202
+ self.assertEqual(404, response.status_code)
203
+ self.assertTrue("error" in response.json)
204
+
205
+ def test_get_no_reports(self):
206
+ self.get_no_rows(self.url)
207
+
208
+ def test_get_all_reports(self):
209
+ item = self.test_new_report_html()
210
+ response = self.client.get(
211
+ self.url, headers=self.get_header_with_auth(self.token)
212
+ )
213
+
214
+ self.assertEqual(1, len(response.json))
215
+ self.assertEqual(item, response.json[0])
216
+
217
+ def test_get_one_report(self):
218
+ item = self.test_new_report_html()
219
+ response = self.client.get(
220
+ f"{self.url}{item['id']}/", headers=self.get_header_with_auth(self.token)
221
+ )
222
+
223
+ content = response.get_data()
224
+
225
+ with open(REPORT_HTML_FILE_PATH, "rb") as f:
226
+ file = f.read()
227
+
228
+ self.assertEqual(200, response.status_code)
229
+ self.assertEqual(content, file)
230
+
231
+ def test_modify_report(self):
232
+ item = self.test_new_report_html()
233
+
234
+ payload = {"name": "new_name", "description": "some_description"}
235
+
236
+ response = self.client.put(
237
+ f"{self.url}{item['id']}/edit/",
238
+ headers=self.get_header_with_auth(
239
+ self.service_token, content_type="multipart/form-data"
240
+ ),
241
+ follow_redirects=True,
242
+ data=payload,
243
+ )
244
+
245
+ self.assertEqual(response.status_code, 200)
246
+
247
+ response = self.client.get(
248
+ f"{self.url}{item['id']}/", headers=self.get_header_with_auth(self.token)
249
+ )
250
+ # response.json
251
+ self.assertEqual(200, response.status_code)
252
+ self.assertEqual("some_description", dict(response.headers)["File-Description"])
253
+
254
+ def test_modify_report_file(self):
255
+ item = self.test_new_report_empty()
256
+
257
+ payload = {"name": "new_name", "description": "some_description"}
258
+ response = self.client.get(
259
+ f"{self.url}{item['id']}/",
260
+ headers=self.get_header_with_auth(self.token),
261
+ )
262
+ self.assertEqual(response.status_code, 200)
263
+
264
+ self.assertIsNone(response.json["file_url"])
265
+
266
+ response = self.client.put(
267
+ f"{self.url}{item['id']}/edit/",
268
+ data=dict(file=(open(REPORT_HTML_FILE_PATH, "rb")), **payload),
269
+ headers=self.get_header_with_auth(
270
+ self.service_token, content_type="multipart/form-data"
271
+ ),
272
+ )
273
+
274
+ self.assertEqual(response.status_code, 200)
275
+
276
+ response = self.client.get(
277
+ f"{self.url}{item['id']}/", headers=self.get_header_with_auth(self.token)
278
+ )
279
+
280
+ self.assertEqual(200, response.status_code)
281
+ self.assertEqual("some_description", dict(response.headers)["File-Description"])
282
+
283
+ # check that the file in the test folder and the one generated on the static folder are equal
284
+ with open(REPORT_HTML_FILE_PATH, "rb") as f:
285
+ file = f.read()
286
+
287
+ content = response.get_data()
288
+
289
+ self.assertEqual(file, content)
290
+ return response.json
291
+
292
+ def test_delete_report(self):
293
+ item = self.test_new_report_html()
294
+ response = self.client.delete(
295
+ f"{self.url}{item['id']}/", headers=self.get_header_with_auth(self.token)
296
+ )
297
+
298
+ self.assertEqual(200, response.status_code)
299
+ self.assertTrue("message" in response.json)
300
+
301
+ my_upload_path = get_report_path(item)
302
+
303
+ self.assertFalse(os.path.exists(my_upload_path))
304
+
305
+ response = self.client.get(
306
+ f"{self.url}{item['id']}/", headers=self.get_header_with_auth(self.token)
307
+ )
308
+ self.assertEqual(404, response.status_code)
@@ -363,7 +363,11 @@ class TestUserEndpoint(TestCase):
363
363
 
364
364
  def test_change_password_rotation(self):
365
365
  current_app.config["PWD_ROTATION_TIME"] = 1 # in days
366
- payload = {"pwd_last_change": (datetime.utcnow() - timedelta(days=2)).strftime("%Y-%m-%dT%H:%M:%SZ")}
366
+ payload = {
367
+ "pwd_last_change": (datetime.utcnow() - timedelta(days=2)).strftime(
368
+ "%Y-%m-%dT%H:%M:%SZ"
369
+ )
370
+ }
367
371
  self.modify_info(self.planner, self.planner, payload)
368
372
  response = self.log_in(self.planner)
369
373
  self.assertEqual(True, response.json["change_password"])
@@ -371,7 +375,6 @@ class TestUserEndpoint(TestCase):
371
375
  payload = {"password": "Newtestpassword1!"}
372
376
  self.modify_info(self.planner, self.planner, payload)
373
377
  self.planner.update(payload)
374
- print(self.planner)
375
378
  response = self.log_in(self.planner)
376
379
  self.assertEqual(False, response.json["change_password"])
377
380
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cornflow
3
- Version: 1.1.0a1
3
+ Version: 1.1.1a1
4
4
  Summary: Cornflow is an open source multi-solver optimization server with a REST API built using flask.
5
5
  Home-page: https://github.com/baobabsoluciones/cornflow
6
6
  Author: baobab soluciones
@@ -12,36 +12,36 @@ Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Development Status :: 5 - Production/Stable
14
14
  Requires-Python: >=3.8
15
- Requires-Dist: alembic ==1.9.2
16
- Requires-Dist: apispec <=6.2.0
17
- Requires-Dist: click <=8.1.3
18
- Requires-Dist: cornflow-client ==1.1.0a1
19
- Requires-Dist: cryptography <=42.0.5
20
- Requires-Dist: disposable-email-domains >=0.0.86
21
- Requires-Dist: Flask ==2.3.2
22
- Requires-Dist: flask-apispec <=0.11.4
23
- Requires-Dist: Flask-Bcrypt <=1.0.1
24
- Requires-Dist: Flask-Compress <=1.13
25
- Requires-Dist: flask-cors <=4.0.1
26
- Requires-Dist: flask-inflate <=0.3
27
- Requires-Dist: Flask-Migrate <=4.0.4
28
- Requires-Dist: Flask-RESTful <=0.3.9
29
- Requires-Dist: Flask-SQLAlchemy ==2.5.1
30
- Requires-Dist: gevent ==23.9.1
31
- Requires-Dist: gunicorn <=22.0.0
32
- Requires-Dist: jsonpatch <=1.32
33
- Requires-Dist: ldap3 <=2.9.1
34
- Requires-Dist: marshmallow <=3.19.0
35
- Requires-Dist: PuLP <=2.7.0
36
- Requires-Dist: psycopg2 <=2.95
37
- Requires-Dist: PyJWT <=2.6.0
38
- Requires-Dist: pytups >=0.86.2
39
- Requires-Dist: requests <=2.31.0
40
- Requires-Dist: SQLAlchemy ==1.3.21
41
- Requires-Dist: webargs <=8.2.0
42
- Requires-Dist: Werkzeug <=3.0.3
43
- Requires-Dist: greenlet <=2.0.2 ; python_version < "3.11"
44
- Requires-Dist: greenlet ==3.0.0 ; python_version >= "3.11"
15
+ Requires-Dist: alembic==1.9.2
16
+ Requires-Dist: apispec<=6.2.0
17
+ Requires-Dist: click<=8.1.3
18
+ Requires-Dist: cornflow-client==1.1.1a1
19
+ Requires-Dist: cryptography<=42.0.5
20
+ Requires-Dist: disposable-email-domains>=0.0.86
21
+ Requires-Dist: Flask==2.3.2
22
+ Requires-Dist: flask-apispec<=0.11.4
23
+ Requires-Dist: Flask-Bcrypt<=1.0.1
24
+ Requires-Dist: Flask-Compress<=1.13
25
+ Requires-Dist: flask-cors<=4.0.1
26
+ Requires-Dist: flask-inflate<=0.3
27
+ Requires-Dist: Flask-Migrate<=4.0.4
28
+ Requires-Dist: Flask-RESTful<=0.3.9
29
+ Requires-Dist: Flask-SQLAlchemy==2.5.1
30
+ Requires-Dist: gevent==23.9.1
31
+ Requires-Dist: gunicorn<=22.0.0
32
+ Requires-Dist: jsonpatch<=1.32
33
+ Requires-Dist: ldap3<=2.9.1
34
+ Requires-Dist: marshmallow<=3.19.0
35
+ Requires-Dist: PuLP<=2.7.0
36
+ Requires-Dist: psycopg2<=2.95
37
+ Requires-Dist: PyJWT<=2.6.0,>=2.0.0
38
+ Requires-Dist: pytups>=0.86.2
39
+ Requires-Dist: requests<=2.31.0
40
+ Requires-Dist: SQLAlchemy==1.3.21
41
+ Requires-Dist: webargs<=8.2.0
42
+ Requires-Dist: Werkzeug<=3.0.3
43
+ Requires-Dist: greenlet<=2.0.2; python_version < "3.11"
44
+ Requires-Dist: greenlet==3.0.0; python_version >= "3.11"
45
45
 
46
46
  Cornflow
47
47
  =========
@@ -5,8 +5,8 @@ airflow_config/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
5
5
  airflow_config/plugins/XCom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  airflow_config/plugins/XCom/gce_xcom_backend.py,sha256=vCGvF2jbfZt5bOv-pk5Q_kUR6LomFUojIymimSJmj3o,1795
7
7
  cornflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- cornflow/app.py,sha256=3tj9aMOLFzBGS4QFPD0Zt2A7N0C5lssvy8NZ-G4sU9E,6997
9
- cornflow/config.py,sha256=CGG2BMn8l1gCB0Okk-8IRrtqiRIUK09fq3xO397ZHig,4738
8
+ cornflow/app.py,sha256=9WV1wrH_6EzaCgBGgpbHu6C8-n0MX_crJI2FxBwR85I,7090
9
+ cornflow/config.py,sha256=MqRw-yQM60BVzU7rC9Ui63_f0VfFIuXceq2mw5WlBNs,5106
10
10
  cornflow/gunicorn.py,sha256=uO-Yk7w7nvQSWh12iDxsVvlG-_2BiKIIjm2UiTk4P9E,480
11
11
  cornflow/cli/__init__.py,sha256=5jBmSMpaE1S9rDaQjS8VHJ6x4FfJG8MhKzMzfw7G4Zc,743
12
12
  cornflow/cli/actions.py,sha256=BdTFucT6gZ0QJqo96Zu0C2G9acZ578tLkktKSfTybJ8,414
@@ -18,7 +18,7 @@ cornflow/cli/roles.py,sha256=NFG__qrlyOT0h4L4nwo9FSV4DKjGtMVh3gwiJxwM37w,411
18
18
  cornflow/cli/schemas.py,sha256=sxuJOZf12SBZAXDiAYNPB-n9LSxzSwkB3xyhgS_4K9A,6086
19
19
  cornflow/cli/service.py,sha256=7_va2Gv1qySldWtTHLL0b_Tg6tuYzAVduyeKmoiBgVs,9292
20
20
  cornflow/cli/users.py,sha256=nPnu8rQNLtwmeXLwYtJ_hjlsa_24XOnQLgBJRBP9bJw,2104
21
- cornflow/cli/utils.py,sha256=0tF41gTt6LL9XGOizTQg2GXuOXbqLg6gapCr-HWjJ0Q,733
21
+ cornflow/cli/utils.py,sha256=2BbC0fVuCXQKAH0j-fltSFtaXxOZHFKwGoU2XDMG65Q,708
22
22
  cornflow/cli/views.py,sha256=Xyx2l-Sm7panxQEfR3qksCIUoqF7woMKsYgZALkxUXM,636
23
23
  cornflow/cli/tools/__init__.py,sha256=JtyhYfUfirw78BV1mCsdeY0W25fDPWTmZhNBWdDh0wA,19
24
24
  cornflow/cli/tools/api_generator.py,sha256=7ZEEGBdL9Anbj5gnPm3m_eHQm0ehz7Y7YaD952mGh58,16344
@@ -37,22 +37,23 @@ cornflow/commands/roles.py,sha256=Oux-UkswkQ74zqaMEJYIEsZpQZGBcGaSahVzx9feAHU,15
37
37
  cornflow/commands/schemas.py,sha256=QjLXLw5So3f8ZqTg5_uvXxwpo4vE0dMT4_gFMKZHGvQ,1828
38
38
  cornflow/commands/users.py,sha256=MEfqMm2ujso0NQgdUm-crOet-G0M43GNqVCx2Ls-2HY,2591
39
39
  cornflow/commands/views.py,sha256=K2Ld1-l1ZKn9m6e2W1LCxmN44QokwR-8u8rIrviiEf8,2276
40
- cornflow/endpoints/__init__.py,sha256=EGUIDL5EGsDQtm1YQ4aKkmRG1roW_3Ki87MeZr79Lx0,7168
40
+ cornflow/endpoints/__init__.py,sha256=Haon-F6Zve6eDAQw6TQH6CS4INHYT2CnTerP4cys8SE,7829
41
41
  cornflow/endpoints/action.py,sha256=ksHK3F919cjkONLcFV2tUIbG-eZw5XbYkqVjYx9iq5I,1359
42
42
  cornflow/endpoints/alarms.py,sha256=3FN7mosBFP_DcJQxfg1h5_phy755FYESXyQ62XpvFbs,1956
43
43
  cornflow/endpoints/apiview.py,sha256=cpxZFkWy6yrRHiAq2tseyVAK1r8uvjnFuOgJjGT0rKI,1370
44
44
  cornflow/endpoints/case.py,sha256=80Fpv9p8mwIXzjQFuyq1PnPTz3RaOUk932sCUfw7yGA,18670
45
45
  cornflow/endpoints/dag.py,sha256=MRthA2pnZCAFfoPbHCLDW2j1BsQ3WdjRGC17Szl4b28,10390
46
46
  cornflow/endpoints/data_check.py,sha256=ZyYR84IT9snjXxUrQfrlv_RzOec_AYeTsijuHYdLAcA,16496
47
- cornflow/endpoints/example_data.py,sha256=fzolSYl1sYCSCR4Ctr7QD9JM3NdxCjBiiQLVxCPCbJg,2441
48
- cornflow/endpoints/execution.py,sha256=5SWwgbxBUj_gDU6Yb7Z-iKNakr9vr3g5qU82Bw9y5wQ,27998
47
+ cornflow/endpoints/example_data.py,sha256=1_qAtZfp51N9sU8WCFDZCXOQiOlxCKJjWbXxDOFZ0C8,4372
48
+ cornflow/endpoints/execution.py,sha256=cPIqt0MQId5ugl3HC82iOSbLY-vRjK_Obe8U1-1TL1I,27999
49
49
  cornflow/endpoints/health.py,sha256=TWmWjKdQOoDzpqwcfksuaAGOLIb2idxzPQcGMWrdkCY,1610
50
50
  cornflow/endpoints/instance.py,sha256=WAnloocXFxSW4vunBJo3CIHx4NzC_0GPJh5bj3ETd9U,11615
51
51
  cornflow/endpoints/licenses.py,sha256=82hHWGYvVIiyw9mlwGtMwJMDJ-ShHOi9rvuM6KvfE4U,873
52
- cornflow/endpoints/login.py,sha256=HMPBQm_yEBzPCvBU_UHlOkUYgtWJG5rL9euR8Dzxm0w,7864
52
+ cornflow/endpoints/login.py,sha256=eVZHo7T-YD080ofUckbPNv0Yhtcp4SaumlVsZb2mOxg,8402
53
53
  cornflow/endpoints/main_alarms.py,sha256=GUB-UdnvEFi7n6FGFKO9VtZeZb4Ox3NvBMhB7rdqNyI,2006
54
54
  cornflow/endpoints/meta_resource.py,sha256=eqC6U8IpY65Cbk2WpdphRtE6o5kes2lB4LhezfUB7xI,8471
55
55
  cornflow/endpoints/permission.py,sha256=FpEBIucfUl89UaJ80SC0VR6pFAdqdSsS43SdNkcXWtI,3751
56
+ cornflow/endpoints/reports.py,sha256=ESYIvG23muEeaRr-plnnVralfeyg7SS68izbxShY4Vg,10198
56
57
  cornflow/endpoints/roles.py,sha256=54ra4MQ9JmrHDsiGczDAVqHgAT4zwhdTA1dLBOy66v8,6105
57
58
  cornflow/endpoints/schemas.py,sha256=lHyvSpPj0x7zVYDlEeRrz_Qqyp6WNimibs5gK4BHpKI,2933
58
59
  cornflow/endpoints/signup.py,sha256=4Xle2aTd6fiblb2pFcTaBP3ykXSuXsrc7qD0JjpqeZY,3513
@@ -68,6 +69,8 @@ cornflow/migrations/versions/00757b557b02_.py,sha256=PtFD0nIRBHjpDiCrhudxReI6ej6
68
69
  cornflow/migrations/versions/1af47a419bbd_.py,sha256=F6XOkxhojBbOSv3EGiWJvvncSMNAUPy2h5-NV2Gd5ak,1926
69
70
  cornflow/migrations/versions/4aac5e0c6e66_.py,sha256=ecWq38w_1vWpbLqsEkTsPw1tGv88OMt9L8JNZHlu7LI,2200
70
71
  cornflow/migrations/versions/7c3ea5ab5501_.py,sha256=TX9Are_ELRweHeGOo3tV4XAB9cFIVH6LAooCvoNfJxU,1569
72
+ cornflow/migrations/versions/83164be03c23_.py,sha256=Ed21NOt_sEdsfdO6MqwkiEjrQu-FQHBwEI1ArA6CGok,1170
73
+ cornflow/migrations/versions/96f00d0961d1_reports_table.py,sha256=nWcJ9wPeQTsbrYGdBoMzQb3dmmPCJgKGw5oSlpAfsMM,1464
71
74
  cornflow/migrations/versions/991b98e24225_.py,sha256=oNDQKQw6SfMdAB9HYV9Vb-haz5dJQo9lp3uJR-K9xYk,834
72
75
  cornflow/migrations/versions/a472b5ad50b7_.py,sha256=RpaLV-eTZmOS4BN53F_o0yG6ZGfmfKIJjrn2x2M6THw,1370
73
76
  cornflow/migrations/versions/c2db9409cb5f_.py,sha256=M6udQ0vaIJXEsGpb31ZqAdU_eDwvbHPvWLvNsGQx7yY,1812
@@ -79,18 +82,19 @@ cornflow/migrations/versions/e1a50dae1ac9_.py,sha256=NIRKFg1hvo4F-YqMdsYoX9VwzKl
79
82
  cornflow/migrations/versions/e937a5234ce4_.py,sha256=460JyCKPN6XL5DDcJfC51WKr9V342ovVhuo8F7fwuo0,710
80
83
  cornflow/migrations/versions/ebdd955fcc5e_.py,sha256=MzLbzmiwMWWVkJWJ8EMmmBnCIOzvlwXKGFWxELnOQpE,1848
81
84
  cornflow/migrations/versions/f3bee20314a2_.py,sha256=pgfAeiPvFvPJXhWlFHq6Y7bjYFGvapsfHEFXXX8UJlE,1782
82
- cornflow/models/__init__.py,sha256=hvUe_9Xep1gl8hPKcWxCZN9sORH0Opskj_DnNs3bn24,500
85
+ cornflow/models/__init__.py,sha256=pbHTYGk7k-HbQYjB8SpC4KFdM1fp838PbdnaPPxiL6M,534
83
86
  cornflow/models/action.py,sha256=8MYzQ2qX5bG0zk28OufypzThkR7AU1J1el-5ABoTurg,1200
84
87
  cornflow/models/alarms.py,sha256=R_g3tkWNSJaAG4gSvthgJlyrueY9VDuIZPoVHk5lDvU,1682
85
88
  cornflow/models/base_data_model.py,sha256=mVMHJpEoJeH6Wly_ZIfzLfTPd39nSYpCgmtA_ft2VPs,5577
86
89
  cornflow/models/case.py,sha256=GEs-xeo0bJ5qJETDnIur-2q2IyR3NSj1K0jP3Arz4Xs,9572
87
90
  cornflow/models/dag.py,sha256=DhHpBqJXrLzPoVSyrS_rYI7BotdzITopJDKsql3mQnQ,2930
88
91
  cornflow/models/dag_permissions.py,sha256=QkhPxSLKxH5elIMdf-rnRtV_CEZBQDFFKUOWv15RgwI,1716
89
- cornflow/models/execution.py,sha256=9sq_GXSAgFgTpDX3kbJGwsHwNQGXH9E_gfNYIfNtDOk,6022
92
+ cornflow/models/execution.py,sha256=UUrQk0w5ZbaM82ZiLA7vJqKS71ZZcgPMSYR3UrEldmk,6275
90
93
  cornflow/models/instance.py,sha256=2E9kBKv1a8soaEAvG8X4qXQ4BVC-IWYD5WQcPmZQw00,3979
91
94
  cornflow/models/main_alarms.py,sha256=9S-Ohr2kYFFWB0HomrpSdDIoUr85Eu1rt90Om_Pa8VY,1748
92
- cornflow/models/meta_models.py,sha256=qeliGdpw0_q0GCeZzansF-09Ay5pueaT-QQPVPZ5aj4,12000
95
+ cornflow/models/meta_models.py,sha256=cCYYWfB-Xm5nh-1bJCFeE8i1vrGElhpO-DQucJ_z8hA,12313
93
96
  cornflow/models/permissions.py,sha256=vPHa0A40e18YLzQEzKk9BrqsDQWfguIlsfrSufmW9dY,2804
97
+ cornflow/models/reports.py,sha256=hZmwd2whHFQYMI2csMzIXqA3iBWhJzfHDjFkmkYBq4w,4568
94
98
  cornflow/models/role.py,sha256=dEASPw8-aLbRRkoyId2zk7lFTq1twpRPMTkwb0zEOIE,2052
95
99
  cornflow/models/user.py,sha256=podqU5Emhe52ytsUnrBcKShk_jSH_0Em0UXZEAmWgjI,8755
96
100
  cornflow/models/user_role.py,sha256=rr-0S4sV5l6xDQIwd94c3bPepDA50NdStwd3MSzRJbU,4974
@@ -101,8 +105,8 @@ cornflow/schemas/alarms.py,sha256=Y-VQ93jbDLtEv49qkNDHwrhwkG7OzEQ0nceqJCqeScQ,54
101
105
  cornflow/schemas/case.py,sha256=OXRsDi_sdB47MQJ59S_1eMjDmLlpUtG7kTFNInV2-cI,2909
102
106
  cornflow/schemas/common.py,sha256=QYuxWcOl4smXFZr_vL07OVgH9H50ZywCrXxycVNr1qA,473
103
107
  cornflow/schemas/dag.py,sha256=0ENA75X9L8YqjJW6ZO1Sb4zE8OxB15_O49_nwA6eAVw,901
104
- cornflow/schemas/example_data.py,sha256=7BeaujSgj10RHK6Z__4wRZ273-QmVjVOs6uEvYw7PnE,146
105
- cornflow/schemas/execution.py,sha256=GSRHzikVPlhxMdiKrGnTuGfen8_Lf4wSfheJwvcavTs,4718
108
+ cornflow/schemas/example_data.py,sha256=hbE8TJakFqOweHXiA3mduNETM6FCX6xLTiQuH3EkSTc,281
109
+ cornflow/schemas/execution.py,sha256=tPqRYFs7KB9-t_vffd9zlM6uIzPOoktvg4mfN3dzQy8,4853
106
110
  cornflow/schemas/health.py,sha256=D2NsP9i6nA1hLema-bvegrrdH4JY7pZlYxPcqRJOvao,141
107
111
  cornflow/schemas/instance.py,sha256=qr4km0AlAhoNf9G1Il-pfHphT_vAiiLDpv7A9S3FKAw,1870
108
112
  cornflow/schemas/main_alarms.py,sha256=cC1_Vb1dmo_vdZpZQrA7jH-hRCjVtLRy6Z2JFBlTrlo,604
@@ -110,6 +114,7 @@ cornflow/schemas/model_json.py,sha256=qUsdd1XmxhcsAmb1JB0xAsvucZoAeQhAQD_3wiY-rV
110
114
  cornflow/schemas/patch.py,sha256=nB6vhmscusfC8tSl4Ded0UwQIbGjGF5_Nwx0kxygKWk,260
111
115
  cornflow/schemas/permissions.py,sha256=dgHKXLDyB1-q-Ii7cuHLpovlFPthtEV3mNxRgTe42ac,1270
112
116
  cornflow/schemas/query.py,sha256=lQ6lMy0O6RRQLA-9JtQ95p70yd7vra4cGIbLrYO74GE,984
117
+ cornflow/schemas/reports.py,sha256=jqsmTXZwg4ZBEozY54XvAvAPZ7T05D0OM-51WF8hiIg,1255
113
118
  cornflow/schemas/role.py,sha256=lZYoLpA0weuDiFgpk3PWrHYJdljvZ3HEIOS-ISNLcCg,469
114
119
  cornflow/schemas/schemas.py,sha256=vNyOwrchuTT3TMR9Jj07pauSr2sFTM-rfIfiKUycOjo,433
115
120
  cornflow/schemas/solution_log.py,sha256=jSutvj0-2RJIqzn7ANLFanAD4jrSDvtgqf6DF6UZBhs,2255
@@ -119,9 +124,9 @@ cornflow/schemas/user_role.py,sha256=e5y6RgdZZtLqD-h2B3sa5WokI5-pT78tWw85IG34I74
119
124
  cornflow/schemas/view.py,sha256=ctq9Y1TmjrWdyOqgDYeEx7qbbuNLKfSiNOlFTlXmpaw,429
120
125
  cornflow/shared/__init__.py,sha256=1ahcBwWOsSjGI4FEm77JBQjitBdBszOncKcEMjzwGYE,29
121
126
  cornflow/shared/compress.py,sha256=pohQaGs1xbH8CN6URIH6BAHA--pFq7Hmjz8oI3c3B5c,1347
122
- cornflow/shared/const.py,sha256=nRZElCjbuJIpjzVlCfZjTN4mAbqDTXIyAbSMlkNL3n8,3440
127
+ cornflow/shared/const.py,sha256=tEe41Ptw_GTsHpKu9cASn5eNIydXtcES_uDjo-4Fmmw,4005
123
128
  cornflow/shared/email.py,sha256=QNDDMv86LZObkevSCyUbLQeR2UD3zWScPIr82NDzYHQ,3437
124
- cornflow/shared/exceptions.py,sha256=BNbC5hzAoC9vDQ3NLM9uLqI14nwCEP1AT3UjeFghnY0,6979
129
+ cornflow/shared/exceptions.py,sha256=btAKuZelxHAwkwCPJZiYeipj4VfHd2cdsYPwLjd0Zv8,7173
125
130
  cornflow/shared/licenses.py,sha256=Lc71Jw2NxVTFWtoXdQ9wJX_o3BDfYg1xVoehDXvnCkQ,1328
126
131
  cornflow/shared/log_config.py,sha256=FM2ajjp2MB4BlFbUHklnWInT7-LLjtrqQ0mo3k_HRmE,621
127
132
  cornflow/shared/query_tools.py,sha256=6yGLCWjv-I2a_ZU4A0IymyJq67fZPZdRcCGOGQQpSXg,1199
@@ -132,44 +137,46 @@ cornflow/shared/authentication/__init__.py,sha256=cJIChk5X6hbA_16usEvfHr8g4JDFI6
132
137
  cornflow/shared/authentication/auth.py,sha256=aQ8oUq9nC3FMbCivPFr2aWQXqP_cDeP6f7ljDhTm-wM,18664
133
138
  cornflow/shared/authentication/decorators.py,sha256=_QpwOU1kYzpaK85Dl0Btdj5hG8Ps47PFgySp_gqhlgk,1276
134
139
  cornflow/shared/authentication/ldap.py,sha256=QfdC2X_ZMcIJabKC5pYWDGMhS5pIOJJvdZXuuiruq-M,4853
140
+ cornflow/static/v1.json,sha256=muwt8Rq63woLy50-wIFKAcq1hTbjnz_tS0jMhhkvfFg,84586
135
141
  cornflow/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
- cornflow/tests/const.py,sha256=_5BYFGN42Xg0PXMR8UU5DBL6dYmYn5rgRBgPyptrKso,2499
137
- cornflow/tests/custom_liveServer.py,sha256=I_0YNrcKIwVmRov3zCQMWwcCWkMe5V246Hpa4gS8AZE,3079
138
- cornflow/tests/custom_test_case.py,sha256=EeAPnI0F5_0ZAQW0_ku0NdTzYxc8se6fi1FtYNdtLTc,25147
142
+ cornflow/tests/const.py,sha256=B7Pc6LIEEogjnxXq-tBXzNRIMf0WktrdJgA4SqaVhXo,2810
143
+ cornflow/tests/custom_live_server.py,sha256=BtSPT9FVtqxf2oHL1kbPnkBNJdCi0aAhnHh3TQrfQMU,3149
144
+ cornflow/tests/custom_test_case.py,sha256=83WvsjxnLRB8FYpbLpz338GGLFqzZKAXoYUod1jcYNY,25144
139
145
  cornflow/tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
- cornflow/tests/integration/test_commands.py,sha256=FZcoEM-05D4MBMe0L0V-0sxk_L0zMbzQxb9UCd7iBe0,695
141
- cornflow/tests/integration/test_cornflowclient.py,sha256=ioAQmQKWW6mXVJhdF4LECZcGIOa_N0xPkFaGWGtxOO8,20963
146
+ cornflow/tests/integration/test_commands.py,sha256=3vLjSK3ji7LYE5ZADJzBHkXRrtxwW_uYVqxcDef749w,696
147
+ cornflow/tests/integration/test_cornflowclient.py,sha256=EZ508fLfO0YC06tzw60zXq9Mxr8MrDFRWWWkzLK4xCE,23894
142
148
  cornflow/tests/ldap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
149
  cornflow/tests/ldap/test_ldap_authentication.py,sha256=6Gu1WkF7MQmcV_10IJkpo2qEloZZ9zjpV18ANDD0HRw,4286
144
150
  cornflow/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
151
  cornflow/tests/unit/test_actions.py,sha256=Fg33PyzNTK4B4NjARelMxLQpQl9nE9JppolkkIY9UEo,1755
146
- cornflow/tests/unit/test_alarms.py,sha256=J4Hp2xIZqpFrojx_RvQCSU1ilDk-iC0vm2z8wZNXwIw,1343
152
+ cornflow/tests/unit/test_alarms.py,sha256=rzh9RBLrGWG6la5acnC1OFJ2wuEWIXbk64fH7oiu8gY,1663
147
153
  cornflow/tests/unit/test_apiview.py,sha256=G5DpUPaKVXgbCOaXXTCjBAeGeCtfR8niltp7B0NNB6o,2107
148
154
  cornflow/tests/unit/test_cases.py,sha256=lXLgvHbNGw8qUoCtYUwwXE_O2AWSmSXxLVlxE-hc9Oc,25974
149
- cornflow/tests/unit/test_cli.py,sha256=IK7nhPpVy2dSXGRSies_Lh9DImNaL2SFCXb-gxKUmDI,12578
150
- cornflow/tests/unit/test_commands.py,sha256=QwGHTOxBOwiIYYQg8wcmSR11lKQk0I8Ltr3sbFERufw,8776
155
+ cornflow/tests/unit/test_cli.py,sha256=8x2Bnpp9gfalqxRw0iVXFf3MdPoVz088zwpN01zENLA,12893
156
+ cornflow/tests/unit/test_commands.py,sha256=WTPjcbvJ_66lWtVUsYPcYFcChgO1kXnNw4hzCo3PyDc,8897
151
157
  cornflow/tests/unit/test_dags.py,sha256=5lTJW_fgh7XXE11Zo9yVsQ7wsmbCPxCCRwna2vkPEuA,10350
152
158
  cornflow/tests/unit/test_data_checks.py,sha256=VjB3AAQOHlqnaRT2jI9L2mNLDAcda6llpiZWkW7nnkk,5471
153
- cornflow/tests/unit/test_example_data.py,sha256=TR6b7ekpc6pLOpDnlKl3fHe-FD7gXw5M1JGVj-Dlfvk,1605
154
- cornflow/tests/unit/test_executions.py,sha256=_hIaiZri7Blyx4DYhBDHh-0peU1HQh66RSPqQJFveE8,17501
159
+ cornflow/tests/unit/test_example_data.py,sha256=D-Tgnqw7NZlnBXaDcUU0reNhAca5JlJP2Sdn3KdS4Sw,4127
160
+ cornflow/tests/unit/test_executions.py,sha256=a6W20kd6Rk22lCnfA6uAsRr-Hhh37GHUg30G_Fa4z7k,17616
155
161
  cornflow/tests/unit/test_generate_from_schema.py,sha256=L1EdnASbDJ8SjrX1V4WnUKKwV0sRTwVnNYnxSpyeSeQ,15376
156
162
  cornflow/tests/unit/test_health.py,sha256=0E0HXMb63_Z8drbLZdxnJwtTbQyaZS9ZEHut6qsDbh8,1033
157
163
  cornflow/tests/unit/test_instances.py,sha256=RaD9Tue2HODKThBNhciu6krdIvrauDLxOq4Y6a_z8DU,10573
158
164
  cornflow/tests/unit/test_instances_file.py,sha256=zXxSlOM_MMkFvpWNX-iatD40xoIAOGQkinCLf1txb0M,1986
159
165
  cornflow/tests/unit/test_licenses.py,sha256=jgnfE4UMFooGn44HK_KspJXIpmLjUpK_WgsBBeTO5eI,1534
160
166
  cornflow/tests/unit/test_log_in.py,sha256=zwVCNO0sGQhpVcUaJnh8cVv2z-qPEYCdI98y61CNyfE,979
161
- cornflow/tests/unit/test_main_alarms.py,sha256=y--A4Ap2X38TCCRgbimzaZ-QvnTqZY8KHCv7C8kTTwc,2060
167
+ cornflow/tests/unit/test_main_alarms.py,sha256=kWQcsy9tBbUu5ox5cmDGgaXov8bRAY1_ru1K4h7U-4E,2300
162
168
  cornflow/tests/unit/test_permissions.py,sha256=4mLj3GI0Bvhy927eXu_RyAmK8i2XD7raYc6W8lyAO04,8782
169
+ cornflow/tests/unit/test_reports.py,sha256=gL_1gQMAi4tMzJtWjC8jOVy9NRjwRo3H6FBbMWn7N0Q,9805
163
170
  cornflow/tests/unit/test_roles.py,sha256=xZ3TohL_sv1ZBPvHv_nnYSsKEhBlrzIchx9soaTb5Ow,16581
164
171
  cornflow/tests/unit/test_schema_from_models.py,sha256=7IfycOGO3U06baX8I-OPJfu-3ZAn5cv8RCdj9wvalMk,4421
165
172
  cornflow/tests/unit/test_schemas.py,sha256=6SpkeYsS3oWntUZEF3GldLqmNa-hpxg-WrKJVTgc-B4,7468
166
173
  cornflow/tests/unit/test_sign_up.py,sha256=-i6VO9z1FwqRHFvaSrpWAzOZx6qa8mHUEmmsjuMXjn8,3481
167
174
  cornflow/tests/unit/test_tables.py,sha256=dY55YgaCkyqwJnqn0LbZHNeXBoL4ZxXWwKkCoTF4WVE,8947
168
175
  cornflow/tests/unit/test_token.py,sha256=OEVPgG8swSMkUbuGJGfGF5Z27utMLICn1eIyma1cM9E,3760
169
- cornflow/tests/unit/test_users.py,sha256=WfaMcybPpR7rspXyvzHGgw25p751hMPAV0DOp_caSPM,22430
176
+ cornflow/tests/unit/test_users.py,sha256=uxKoPqNtpiPh6JADh6kXLTmLSxNMYw44hsA3JTmo1Fw,22454
170
177
  cornflow/tests/unit/tools.py,sha256=ag3sWv2WLi498R1GL5AOUnXqSsszD3UugzLZLC5NqAw,585
171
- cornflow-1.1.0a1.dist-info/METADATA,sha256=TFEqw1OCDTa8w9adMHT5zMsibVdTOrokQgEYHG6wRkc,9402
172
- cornflow-1.1.0a1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
173
- cornflow-1.1.0a1.dist-info/entry_points.txt,sha256=r5wKLHpuyVLMUIZ5I29_tpqYf-RuP-3w_8DhFi8_blQ,47
174
- cornflow-1.1.0a1.dist-info/top_level.txt,sha256=Qj9kLFJW1PLb-ZV2s_aCkQ-Wi5W6KC6fFR-LTBrx-rU,24
175
- cornflow-1.1.0a1.dist-info/RECORD,,
178
+ cornflow-1.1.1a1.dist-info/METADATA,sha256=ujrEhaExOsV11jZVIhl7t1qmEf9VUfkvfmkk7cYFVZw,9378
179
+ cornflow-1.1.1a1.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
180
+ cornflow-1.1.1a1.dist-info/entry_points.txt,sha256=r5wKLHpuyVLMUIZ5I29_tpqYf-RuP-3w_8DhFi8_blQ,47
181
+ cornflow-1.1.1a1.dist-info/top_level.txt,sha256=Qj9kLFJW1PLb-ZV2s_aCkQ-Wi5W6KC6fFR-LTBrx-rU,24
182
+ cornflow-1.1.1a1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: bdist_wheel (0.44.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5