meta-edc 1.0.7__py3-none-any.whl → 1.1.1__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 (63) hide show
  1. meta_ae/action_items.py +10 -2
  2. meta_ae/baker_recipes.py +1 -2
  3. meta_ae/tests/tests/test_actions.py +1 -2
  4. meta_analytics/README.rst +1 -2
  5. meta_analytics/notebooks/anu.ipynb +95 -0
  6. meta_analytics/notebooks/appointment_planning.ipynb +329 -0
  7. meta_analytics/notebooks/arvs.ipynb +103 -0
  8. meta_analytics/notebooks/cleaning/consent_v1_ext.ipynb +227 -0
  9. meta_analytics/notebooks/cleaning/offschedule_eos.ipynb +353 -0
  10. meta_analytics/notebooks/dsmc/renal_dysfunction.ipynb +435 -0
  11. meta_analytics/notebooks/endpoints/meta_endpoints_by_date.ipynb +664 -0
  12. meta_analytics/notebooks/followup_examination.ipynb +141 -0
  13. meta_analytics/notebooks/hba1c.ipynb +136 -0
  14. meta_analytics/notebooks/hiv_regimens.ipynb +122 -118
  15. meta_analytics/notebooks/incidence.ipynb +232 -0
  16. meta_analytics/notebooks/liver.ipynb +389 -0
  17. meta_analytics/notebooks/magreth.ipynb +645 -0
  18. meta_analytics/notebooks/monitoring_report.ipynb +721 -448
  19. meta_analytics/notebooks/pharmacy.ipynb +405 -306
  20. meta_analytics/notebooks/pharmacy_stock_202410.ipynb +306 -0
  21. meta_analytics/notebooks/steering.ipynb +61 -0
  22. meta_analytics/notebooks/undiagnosed/meta3_screening_consort_chart.ipynb +1176 -0
  23. meta_analytics/notebooks/undiagnosed/meta3_screening_undiagnosed.ipynb +519 -0
  24. meta_analytics/notebooks/undiagnosed/meta_screening_table2.ipynb +964 -0
  25. meta_analytics/notebooks/undiagnosed/screen_undiagnosed_or.ipynb +296 -0
  26. meta_analytics/notebooks/undiagnosed/screening.ipynb +273 -0
  27. meta_analytics/notebooks/undiagnosed/screening2.ipynb +958 -0
  28. meta_analytics/notebooks/undiagnosed/screening_undiagnosed_20241002.ipynb +958 -0
  29. meta_analytics/notebooks/ven.ipynb +191 -0
  30. meta_analytics/notebooks/vitals.ipynb +263 -0
  31. meta_edc/settings/debug.py +3 -2
  32. meta_edc/urls.py +1 -0
  33. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/METADATA +3 -3
  34. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/RECORD +62 -35
  35. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/WHEEL +1 -1
  36. meta_labs/reportables.py +14 -11
  37. meta_labs/tests/test_reportables.py +33 -12
  38. meta_pharmacy/notebooks/pharmacy.ipynb +41 -0
  39. meta_prn/admin/offschedule_pregnancy_admin.py +3 -3
  40. meta_prn/admin/onschedule_dm_referral_admin.py +5 -5
  41. meta_prn/form_validators/end_of_study.py +2 -2
  42. meta_prn/migrations/0063_historicaloffstudymedication_singleton_field_and_more.py +37 -0
  43. meta_prn/migrations/0064_auto_20250602_2143.py +18 -0
  44. meta_prn/models/end_of_study.py +2 -0
  45. meta_prn/models/off_study_medication.py +2 -0
  46. meta_reports/admin/last_imp_refill_admin.py +3 -2
  47. meta_screening/eligibility/eligibility_part_three/base_eligibility_part_three.py +59 -47
  48. meta_screening/form_validators/screening_part_three.py +6 -1
  49. meta_screening/tests/meta_test_case_mixin.py +3 -0
  50. meta_screening/tests/tests/test_forms.py +9 -2
  51. meta_screening/tests/tests/test_screening_part_three.py +11 -14
  52. meta_subject/action_items.py +2 -3
  53. meta_subject/choices.py +2 -1
  54. meta_subject/form_validators/delivery_form_validator.py +1 -0
  55. meta_subject/forms/blood_results/blood_results_rft_form.py +60 -3
  56. meta_subject/forms/delivery_form.py +2 -0
  57. meta_subject/migrations/0223_bloodresultsfbc_errors_bloodresultsgludummy_errors_and_more.py +83 -0
  58. meta_subject/migrations/0224_bloodresultsfbc_abnormal_summary_and_more.py +153 -0
  59. meta_subject/tests/tests/test_egfr.py +5 -5
  60. meta_analytics/dataframes/enrolled/__init__.py +0 -0
  61. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/licenses/AUTHORS.rst +0 -0
  62. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/licenses/LICENSE +0 -0
  63. {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,191 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "0",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "%%capture\n",
11
+ "import os\n",
12
+ "from pathlib import Path\n",
13
+ "import pandas as pd\n",
14
+ "from dj_notebook import activate\n",
15
+ "import numpy as np\n",
16
+ "from django_pandas.io import read_frame\n",
17
+ "\n",
18
+ "env_file = os.environ[\"META_ENV\"]\n",
19
+ "reports_folder = Path(os.environ[\"META_REPORTS_FOLDER\"])\n",
20
+ "analysis_folder = Path(os.environ[\"META_ANALYSIS_FOLDER\"])\n",
21
+ "pharmacy_folder = Path(os.environ[\"META_PHARMACY_FOLDER\"])\n",
22
+ "plus = activate(dotenv_file=env_file)\n",
23
+ "pd.set_option('future.no_silent_downcasting', True)"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": null,
29
+ "id": "1",
30
+ "metadata": {},
31
+ "outputs": [],
32
+ "source": [
33
+ "from matplotlib import pyplot as plt\n",
34
+ "from matplotlib_venn import venn3, venn2\n",
35
+ "from meta_analytics.dataframes import get_screening_df\n",
36
+ "\n"
37
+ ]
38
+ },
39
+ {
40
+ "cell_type": "code",
41
+ "execution_count": null,
42
+ "id": "2",
43
+ "metadata": {},
44
+ "outputs": [],
45
+ "source": [
46
+ "def get_fbg_value(r):\n",
47
+ " if not pd.isna(r[\"converted_fbg2_value\"]):\n",
48
+ " return r[\"converted_fbg2_value\"]\n",
49
+ " return r[\"converted_fbg_value\"]\n",
50
+ "\n",
51
+ "def get_ogtt_value(r):\n",
52
+ " if not pd.isna(r[\"converted_ogtt2_value\"]):\n",
53
+ " return r[\"converted_ogtt2_value\"]\n",
54
+ " return r[\"converted_ogtt_value\"]\n"
55
+ ]
56
+ },
57
+ {
58
+ "cell_type": "code",
59
+ "execution_count": null,
60
+ "id": "3",
61
+ "metadata": {},
62
+ "outputs": [],
63
+ "source": [
64
+ "from meta_analytics.dataframes import get_screening_df\n",
65
+ "\n",
66
+ "df_screening = get_screening_df()\n",
67
+ "df_screening[\"visit_code\"] = \"Enrol\"\n",
68
+ "df_screening[\"fbg_value\"] = df_screening.apply(get_fbg_value, axis=1)\n",
69
+ "df_screening[\"ogtt_value\"] = df_screening.apply(get_ogtt_value, axis=1)\n",
70
+ "df_screening[\"site_id\"] = df_screening.site.astype(int)\n",
71
+ "df_screening = df_screening.drop(columns=[\"site\"])\n"
72
+ ]
73
+ },
74
+ {
75
+ "cell_type": "code",
76
+ "execution_count": null,
77
+ "id": "4",
78
+ "metadata": {},
79
+ "outputs": [],
80
+ "source": [
81
+ "df_screening.query(\"\")"
82
+ ]
83
+ },
84
+ {
85
+ "cell_type": "code",
86
+ "execution_count": null,
87
+ "id": "5",
88
+ "metadata": {},
89
+ "outputs": [],
90
+ "source": [
91
+ "fbg = set(df_screening[df_screening.fbg_value>=7.0][[\"id\"]].id.to_list())\n",
92
+ "ogtt = set(df_screening[df_screening.ogtt_value>=11.1][[\"id\"]].id.to_list())\n",
93
+ "hba1c = set(df_screening[df_screening.hba1c_value>=6.5][[\"id\"]].id.to_list())\n"
94
+ ]
95
+ },
96
+ {
97
+ "cell_type": "code",
98
+ "execution_count": null,
99
+ "id": "6",
100
+ "metadata": {},
101
+ "outputs": [],
102
+ "source": [
103
+ "\n",
104
+ "# plt.figure(figsize=(6, 6))\n",
105
+ "fig, ax = plt.subplots(figsize=(8, 8))\n",
106
+ "venn = venn3([fbg, ogtt, hba1c], set_labels=('FBG≥7.0 mmol/L', 'OGTT≥11.1 mmol/L', 'HBA1C≥6.5%'), ax=ax)\n",
107
+ "plt.title(\"Overlap in diabetes indicators for all screened patients (n=5552)\")\n",
108
+ "\n",
109
+ "region_ids = ['100', '010', '001']\n",
110
+ "for idx, region_id in enumerate(region_ids):\n",
111
+ " patch = venn.get_patch_by_id(region_id)\n",
112
+ " label = venn.set_labels[idx]\n",
113
+ " if patch and label:\n",
114
+ " label.set_color(patch.get_facecolor())\n",
115
+ " label.set_fontweight('bold')\n",
116
+ "\n",
117
+ "# Show the plot\n",
118
+ "# plt.show()\n",
119
+ "plt.savefig(analysis_folder / \"meta3_venn.png\", bbox_inches='tight')\n",
120
+ "\n"
121
+ ]
122
+ },
123
+ {
124
+ "cell_type": "code",
125
+ "execution_count": null,
126
+ "id": "7",
127
+ "metadata": {},
128
+ "outputs": [],
129
+ "source": []
130
+ },
131
+ {
132
+ "cell_type": "code",
133
+ "execution_count": null,
134
+ "id": "8",
135
+ "metadata": {},
136
+ "outputs": [],
137
+ "source": [
138
+ "\n",
139
+ "import matplotlib.pyplot as plt\n",
140
+ "from matplotlib_venn import venn2\n",
141
+ "from pathlib import Path\n",
142
+ "\n",
143
+ "# Define the output folder\n",
144
+ "analysis_folder = Path(\"analysis_output\")\n",
145
+ "analysis_folder.mkdir(parents=True, exist_ok=True)\n",
146
+ "\n",
147
+ "# Define the sets\n",
148
+ "set1 = set(['A', 'B', 'C', 'D'])\n",
149
+ "set2 = set(['C', 'D', 'E', 'F'])\n",
150
+ "\n",
151
+ "# Create the figure and axis\n",
152
+ "fig, ax = plt.subplots(figsize=(6, 6))\n",
153
+ "\n",
154
+ "# Draw the Venn diagram on the axis\n",
155
+ "venn2([set1, set2], set_labels=('Set 1', 'Set 2'), ax=ax)\n",
156
+ "\n",
157
+ "# Save the figure\n",
158
+ "fig.savefig(analysis_folder / \"meta3_venn.png\", bbox_inches='tight')\n"
159
+ ]
160
+ },
161
+ {
162
+ "cell_type": "code",
163
+ "execution_count": null,
164
+ "id": "9",
165
+ "metadata": {},
166
+ "outputs": [],
167
+ "source": []
168
+ }
169
+ ],
170
+ "metadata": {
171
+ "kernelspec": {
172
+ "display_name": "Python 3",
173
+ "language": "python",
174
+ "name": "python3"
175
+ },
176
+ "language_info": {
177
+ "codemirror_mode": {
178
+ "name": "ipython",
179
+ "version": 2
180
+ },
181
+ "file_extension": ".py",
182
+ "mimetype": "text/x-python",
183
+ "name": "python",
184
+ "nbconvert_exporter": "python",
185
+ "pygments_lexer": "ipython2",
186
+ "version": "2.7.6"
187
+ }
188
+ },
189
+ "nbformat": 4,
190
+ "nbformat_minor": 5
191
+ }
@@ -0,0 +1,263 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "0",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "%%capture\n",
11
+ "import os\n",
12
+ "import pandas as pd\n",
13
+ "from dj_notebook import activate\n",
14
+ "from pathlib import Path\n",
15
+ "env_file = os.environ[\"META_ENV\"]\n",
16
+ "analysis_folder = Path(os.environ[\"META_ANALYSIS_FOLDER\"])\n",
17
+ "reports_folder = Path(os.environ[\"META_ANALYSIS_FOLDER\"])\n",
18
+ "plus = activate(dotenv_file=env_file)"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "id": "1",
25
+ "metadata": {},
26
+ "outputs": [],
27
+ "source": [
28
+ "from edc_pdutils.dataframes import get_crf\n",
29
+ "from edc_appointment.analytics import get_appointment_df\n",
30
+ "from edc_appointment.constants import MISSED_APPT\n",
31
+ "\n"
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "code",
36
+ "execution_count": null,
37
+ "id": "2",
38
+ "metadata": {},
39
+ "outputs": [],
40
+ "source": [
41
+ "df_visit = get_crf(\"meta_subject.glucosefbg\", subject_visit_model=\"meta_subject.subjectvisit\")"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "code",
46
+ "execution_count": null,
47
+ "id": "3",
48
+ "metadata": {},
49
+ "outputs": [],
50
+ "source": [
51
+ "df_missedvisit = get_crf(\"meta_subject.subjectvisitmissed\", subject_visit_model=\"meta_subject.subjectvisit\")\n"
52
+ ]
53
+ },
54
+ {
55
+ "cell_type": "code",
56
+ "execution_count": null,
57
+ "id": "4",
58
+ "metadata": {},
59
+ "outputs": [],
60
+ "source": [
61
+ "df_missedvisit[df_missedvisit.appt_timing!=MISSED_APPT]"
62
+ ]
63
+ },
64
+ {
65
+ "cell_type": "code",
66
+ "execution_count": null,
67
+ "id": "5",
68
+ "metadata": {},
69
+ "outputs": [],
70
+ "source": []
71
+ },
72
+ {
73
+ "cell_type": "code",
74
+ "execution_count": null,
75
+ "id": "6",
76
+ "metadata": {},
77
+ "outputs": [],
78
+ "source": [
79
+ "dffbg = get_crf(\"meta_subject.glucosefbg\", subject_visit_model=\"meta_subject.subjectvisit\")"
80
+ ]
81
+ },
82
+ {
83
+ "cell_type": "code",
84
+ "execution_count": null,
85
+ "id": "7",
86
+ "metadata": {},
87
+ "outputs": [],
88
+ "source": [
89
+ "dffbg[dffbg.fbg_value<=3.0][[\"subject_identifier\", \"visit_code\", \"fbg_value\"]]"
90
+ ]
91
+ },
92
+ {
93
+ "cell_type": "code",
94
+ "execution_count": null,
95
+ "id": "8",
96
+ "metadata": {},
97
+ "outputs": [],
98
+ "source": [
99
+ "dfglu = get_crf(\"meta_subject.glucose\", subject_visit_model=\"meta_subject.subjectvisit\")\n"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "code",
104
+ "execution_count": null,
105
+ "id": "9",
106
+ "metadata": {},
107
+ "outputs": [],
108
+ "source": [
109
+ "dfglu.fbg_value.describe()\n"
110
+ ]
111
+ },
112
+ {
113
+ "cell_type": "code",
114
+ "execution_count": null,
115
+ "id": "10",
116
+ "metadata": {},
117
+ "outputs": [],
118
+ "source": [
119
+ "df_appt = get_appointment_df()"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "code",
124
+ "execution_count": null,
125
+ "id": "11",
126
+ "metadata": {},
127
+ "outputs": [],
128
+ "source": [
129
+ "df_appt"
130
+ ]
131
+ },
132
+ {
133
+ "cell_type": "code",
134
+ "execution_count": null,
135
+ "id": "12",
136
+ "metadata": {},
137
+ "outputs": [],
138
+ "source": [
139
+ "dffbg.visit_code.value_counts()"
140
+ ]
141
+ },
142
+ {
143
+ "cell_type": "code",
144
+ "execution_count": null,
145
+ "id": "13",
146
+ "metadata": {},
147
+ "outputs": [],
148
+ "source": [
149
+ "dfglu.visit_code.value_counts()\n"
150
+ ]
151
+ },
152
+ {
153
+ "cell_type": "code",
154
+ "execution_count": null,
155
+ "id": "14",
156
+ "metadata": {},
157
+ "outputs": [],
158
+ "source": [
159
+ "df = df_appt.merge(dffbg[[\"subject_identifier\", \"visit_code\", \"fbg_value\"]], on=[\"subject_identifier\", \"visit_code\"], how=\"left\")"
160
+ ]
161
+ },
162
+ {
163
+ "cell_type": "code",
164
+ "execution_count": null,
165
+ "id": "15",
166
+ "metadata": {},
167
+ "outputs": [],
168
+ "source": [
169
+ "df[df.visit_code==1005.0].appt_status.value_counts()"
170
+ ]
171
+ },
172
+ {
173
+ "cell_type": "code",
174
+ "execution_count": null,
175
+ "id": "16",
176
+ "metadata": {},
177
+ "outputs": [],
178
+ "source": [
179
+ "df[(df.visit_code==1005.0) & (df.fbg_value.isna())].appt_status.value_counts()\n"
180
+ ]
181
+ },
182
+ {
183
+ "cell_type": "code",
184
+ "execution_count": null,
185
+ "id": "17",
186
+ "metadata": {},
187
+ "outputs": [],
188
+ "source": [
189
+ "from datetime import datetime\n",
190
+ "\n",
191
+ "df[(df.visit_code==1005.0) & (df.fbg_value.isna()) & (df.appt_datetime<=pd.to_datetime(datetime(2024,3,4)))].appt_status.value_counts()"
192
+ ]
193
+ },
194
+ {
195
+ "cell_type": "code",
196
+ "execution_count": null,
197
+ "id": "18",
198
+ "metadata": {},
199
+ "outputs": [],
200
+ "source": [
201
+ "missed_subjects = [\n",
202
+ " \"105-60-0164-5\",\n",
203
+ " \"105-20-0384-3\",\n",
204
+ " \"105-60-0196-7\",\n",
205
+ " \"105-60-0157-9\",\n",
206
+ " \"105-40-0324-7\",\n",
207
+ " \"105-30-0118-4\",\n",
208
+ "]\n",
209
+ "\n",
210
+ "df[(df.visit_code==1005.0) & (df.fbg_value.isna()) & (df.appt_datetime<=pd.to_datetime(datetime(2024,3,4)))].subject_identifier"
211
+ ]
212
+ },
213
+ {
214
+ "cell_type": "code",
215
+ "execution_count": null,
216
+ "id": "19",
217
+ "metadata": {},
218
+ "outputs": [],
219
+ "source": [
220
+ "df[(df.visit_code==1005.0) & (df.fbg_value.isna()) & (df.appt_datetime<=pd.to_datetime(datetime(2024,3,4))) & (df.appt_timing) ][[\"subject_identifier\", \"appt_timing\", \"appt_status\", \"visit_code\"]]\n"
221
+ ]
222
+ },
223
+ {
224
+ "cell_type": "code",
225
+ "execution_count": null,
226
+ "id": "20",
227
+ "metadata": {},
228
+ "outputs": [],
229
+ "source": [
230
+ "df_appt[df_appt.subject_identifier==\"105-60-0157-9\"]"
231
+ ]
232
+ },
233
+ {
234
+ "cell_type": "code",
235
+ "execution_count": null,
236
+ "id": "21",
237
+ "metadata": {},
238
+ "outputs": [],
239
+ "source": []
240
+ }
241
+ ],
242
+ "metadata": {
243
+ "kernelspec": {
244
+ "display_name": "Python 3",
245
+ "language": "python",
246
+ "name": "python3"
247
+ },
248
+ "language_info": {
249
+ "codemirror_mode": {
250
+ "name": "ipython",
251
+ "version": 2
252
+ },
253
+ "file_extension": ".py",
254
+ "mimetype": "text/x-python",
255
+ "name": "python",
256
+ "nbconvert_exporter": "python",
257
+ "pygments_lexer": "ipython2",
258
+ "version": "2.7.6"
259
+ }
260
+ },
261
+ "nbformat": 4,
262
+ "nbformat_minor": 5
263
+ }
@@ -7,12 +7,13 @@ from .defaults import * # noqa
7
7
  print(f"Settings file {__file__}")
8
8
 
9
9
  # TZ Sites:
10
- # SITE_ID = SiteID(default=20) # Amana
10
+ SITE_ID = SiteID(default=20) # Amana
11
11
  # SITE_ID = SiteID(default=10) # Hindu Mandal
12
12
  # SITE_ID = SiteID(default=40) # Mwananyamala
13
13
  # SITE_ID = SiteID(default=50) # Mbagala
14
- SITE_ID = SiteID(default=60) # Mnazi-Moja
14
+ # SITE_ID = SiteID(default=60) # Mnazi-Moja
15
15
  # SITE_ID = SiteID(default=30) # Temeke
16
+
16
17
  INDEX_PAGE = "http://localhost:8000"
17
18
  EDC_SITES_UAT_DOMAIN = False
18
19
  DEBUG = True
meta_edc/urls.py CHANGED
@@ -51,6 +51,7 @@ urlpatterns = [
51
51
  *paths_for_urlpatterns("edc_protocol_incident"),
52
52
  *paths_for_urlpatterns("edc_qol"),
53
53
  *paths_for_urlpatterns("edc_randomization"),
54
+ *paths_for_urlpatterns("edc_reportable"),
54
55
  *paths_for_urlpatterns("edc_refusal"),
55
56
  *paths_for_urlpatterns("edc_registration"),
56
57
  *paths_for_urlpatterns("edc_review_dashboard"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-edc
3
- Version: 1.0.7
3
+ Version: 1.1.1
4
4
  Summary: META Trial EDC (http://www.isrctn.com/ISRCTN76157257)
5
5
  Home-page: https://github.com/meta-trial/meta-edc
6
6
  Author: Erik van Widenfelt
@@ -683,7 +683,7 @@ License: GNU GENERAL PUBLIC LICENSE
683
683
  Keywords: django,clinicedc,META EDC,EDC,clinical trials
684
684
  Classifier: Environment :: Web Environment
685
685
  Classifier: Framework :: Django
686
- Classifier: Framework :: Django :: 5.1
686
+ Classifier: Framework :: Django :: 5.2
687
687
  Classifier: Intended Audience :: Developers
688
688
  Classifier: Intended Audience :: Science/Research
689
689
  Classifier: Operating System :: OS Independent
@@ -693,7 +693,7 @@ Requires-Python: >=3.12
693
693
  Description-Content-Type: text/x-rst
694
694
  License-File: LICENSE
695
695
  License-File: AUTHORS.rst
696
- Requires-Dist: edc==1.0.9
696
+ Requires-Dist: edc==1.1.1
697
697
  Requires-Dist: edc-microscopy
698
698
  Requires-Dist: beautifulsoup4
699
699
  Requires-Dist: celery[redis]