clinicedc 2.0.7__py3-none-any.whl → 2.0.8__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.

Potentially problematic release.


This version of clinicedc might be problematic. Click here for more details.

Files changed (140) hide show
  1. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/METADATA +1 -1
  2. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/RECORD +134 -137
  3. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
  4. edc_action_item/auths.py +37 -32
  5. edc_action_item/models/action_model_mixin.py +1 -2
  6. edc_action_item/models/signals.py +22 -23
  7. edc_action_item/site_action_items.py +5 -9
  8. edc_action_item/utils.py +3 -3
  9. edc_adverse_event/auths.py +55 -51
  10. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
  11. edc_appointment/auths.py +14 -10
  12. edc_appointment/creators/appointment_creator.py +1 -1
  13. edc_appointment/creators/appointments_creator.py +1 -1
  14. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
  15. edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
  16. edc_appointment/models/appointment.py +1 -1
  17. edc_appointment/utils.py +19 -24
  18. edc_auth/auth_objects/__init__.py +2 -20
  19. edc_auth/auth_objects/default_groups.py +13 -11
  20. edc_auth/auth_objects/default_roles.py +26 -24
  21. edc_auth/auth_updater/auth_updater.py +13 -2
  22. edc_auth/auth_updater/group_updater.py +12 -10
  23. edc_auth/auth_updater/role_updater.py +2 -2
  24. edc_auth/constants.py +10 -0
  25. edc_auth/import_users.py +3 -3
  26. edc_auth/models/user_profile.py +14 -11
  27. edc_auth/site_auths.py +80 -67
  28. edc_consent/auths.py +18 -12
  29. edc_constants/constants.py +1 -0
  30. edc_crf/auths.py +5 -0
  31. edc_dashboard/auths.py +10 -6
  32. edc_dashboard/url_config.py +92 -83
  33. edc_dashboard/url_names.py +4 -4
  34. edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
  35. edc_data_manager/admin/data_query_admin.py +12 -11
  36. edc_data_manager/auths.py +37 -34
  37. edc_data_manager/rule/query_rule_wrapper.py +7 -7
  38. edc_export/archive_exporter.py +3 -2
  39. edc_export/auths.py +32 -28
  40. edc_export/model_exporter/model_exporter.py +4 -1
  41. edc_facility/auths.py +8 -3
  42. edc_facility/facility.py +8 -9
  43. edc_form_label/custom_label_condition.py +11 -8
  44. edc_form_label/form_label.py +1 -1
  45. edc_form_runners/auths.py +11 -6
  46. edc_form_validators/applicable_field_validator.py +7 -6
  47. edc_form_validators/base_form_validator.py +8 -9
  48. edc_form_validators/other_specify_field_validator.py +2 -8
  49. edc_form_validators/required_field_validator.py +19 -16
  50. edc_identifier/research_identifier.py +11 -10
  51. edc_identifier/simple_identifier.py +8 -2
  52. edc_lab/auths.py +26 -23
  53. edc_lab/lab/aliquot_creator.py +5 -8
  54. edc_lab/lab/primary_aliquot.py +14 -5
  55. edc_lab/model_mixins/requisition/requisition_model_mixin.py +6 -8
  56. edc_lab/models/aliquot.py +2 -2
  57. edc_lab/models/manifest/manifest.py +2 -2
  58. edc_lab/models/manifest/manifest_item.py +1 -1
  59. edc_lab_dashboard/auths.py +16 -11
  60. edc_lab_results/calculate_missing.py +8 -8
  61. edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
  62. edc_lab_results/get_summary.py +26 -25
  63. edc_lab_results/model_mixins/blood_result_model_mixin.py +2 -0
  64. edc_label/auths.py +6 -1
  65. edc_label/label_template.py +8 -8
  66. edc_list_data/load_model_data.py +3 -3
  67. edc_list_data/post_migrate_signals.py +1 -1
  68. edc_list_data/preload_data.py +2 -2
  69. edc_list_data/row.py +1 -1
  70. edc_list_data/site_list_data.py +6 -5
  71. edc_locator/auths.py +18 -13
  72. edc_metadata/auths.py +11 -7
  73. edc_metadata/metadata/metadata.py +1 -1
  74. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  75. edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
  76. edc_metadata/metadata_rules/rule.py +2 -3
  77. edc_metadata/metadata_rules/rule_evaluator.py +1 -1
  78. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
  79. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
  80. edc_metadata/models/signals.py +10 -11
  81. edc_navbar/auths.py +18 -13
  82. edc_notification/auths.py +9 -4
  83. edc_notification/notification/graded_event_notification.py +2 -2
  84. edc_notification/notification/model_notification.py +3 -30
  85. edc_notification/notification/new_model_notification.py +1 -1
  86. edc_notification/notification/notification.py +1 -1
  87. edc_notification/notification/updated_model_notification.py +2 -2
  88. edc_offstudy/auths.py +12 -7
  89. edc_pdutils/df_exporters/csv_model_exporter.py +5 -2
  90. edc_pharmacy/auths.py +19 -15
  91. edc_pharmacy/models/medication/formulation.py +5 -7
  92. edc_pharmacy/prescribe/create_prescription.py +3 -3
  93. edc_pharmacy/utils/confirm_stock.py +1 -1
  94. edc_pharmacy/utils/confirm_stock_at_site.py +1 -1
  95. edc_pharmacy/views/confirmation_at_site_view.py +6 -9
  96. edc_prn/admin_site.py +5 -0
  97. edc_prn/prn.py +10 -11
  98. edc_prn/urls.py +11 -0
  99. edc_protocol_incident/action_items.py +4 -4
  100. edc_protocol_incident/auths.py +27 -20
  101. edc_pylabels/auths.py +6 -1
  102. edc_qareports/auths.py +11 -7
  103. edc_randomization/admin.py +30 -24
  104. edc_randomization/auths.py +12 -7
  105. edc_randomization/randomizer.py +22 -20
  106. edc_randomization/utils.py +17 -16
  107. edc_refusal/auths.py +7 -2
  108. edc_refusal/model_mixins.py +1 -1
  109. edc_registration/auths.py +28 -23
  110. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +13 -4
  111. edc_registration/models/registered_subject.py +1 -1
  112. edc_reportable/utils/get_reference_range_collection.py +2 -3
  113. edc_reportable/utils/load_data.py +1 -1
  114. edc_review_dashboard/auths.py +23 -18
  115. edc_screening/age_evaluator.py +3 -3
  116. edc_screening/auths.py +35 -30
  117. edc_screening/eligibility.py +1 -1
  118. edc_screening/gender_evaluator.py +1 -1
  119. edc_screening/model_mixins/eligibility_model_mixin.py +0 -2
  120. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  121. edc_screening/screening_eligibility.py +2 -4
  122. edc_screening/utils.py +9 -9
  123. edc_search/generate_slug.py +26 -0
  124. edc_search/model_mixins.py +10 -21
  125. edc_sites/auths.py +8 -3
  126. edc_subject_dashboard/auths.py +27 -22
  127. edc_timepoint/apps.py +0 -21
  128. edc_unblinding/auths.py +9 -4
  129. edc_utils/__init__.py +3 -1
  130. edc_utils/show_urls.py +29 -2
  131. edc_visit_schedule/auths.py +6 -1
  132. edc_visit_schedule/site_visit_schedules.py +2 -2
  133. edc_visit_tracking/models/signals.py +2 -2
  134. edc_form_label/models.py +0 -0
  135. edc_search/constants.py +0 -1
  136. edc_search/models.py +0 -0
  137. edc_search/search_slug.py +0 -51
  138. edc_search/updater.py +0 -30
  139. edc_search/wsgi.py +0 -7
  140. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
edc_consent/auths.py CHANGED
@@ -6,15 +6,21 @@ from edc_auth.utils import remove_default_model_permissions_from_edc_permissions
6
6
 
7
7
  from .auth_objects import consent_codenames, navbar_tuples
8
8
 
9
- site_auths.add_post_update_func(
10
- "edc_consent",
11
- remove_default_model_permissions_from_edc_permissions,
12
- )
13
-
14
- site_auths.add_custom_permissions_tuples(
15
- model="edc_consent.edcpermissions", codename_tuples=navbar_tuples
16
- )
17
-
18
- site_auths.update_group(*consent_codenames, name=PII, no_delete=True)
19
- site_auths.update_group(*consent_codenames, name=PII_VIEW, view_only=True)
20
- site_auths.add_pii_model(settings.SUBJECT_CONSENT_MODEL)
9
+
10
+ def update_site_auths():
11
+
12
+ site_auths.add_post_update_func(
13
+ "edc_consent",
14
+ remove_default_model_permissions_from_edc_permissions,
15
+ )
16
+
17
+ site_auths.add_custom_permissions_tuples(
18
+ model="edc_consent.edcpermissions", codename_tuples=navbar_tuples
19
+ )
20
+
21
+ site_auths.update_group(*consent_codenames, name=PII, no_delete=True)
22
+ site_auths.update_group(*consent_codenames, name=PII_VIEW, view_only=True)
23
+ site_auths.add_pii_model(settings.SUBJECT_CONSENT_MODEL)
24
+
25
+
26
+ update_site_auths()
@@ -135,6 +135,7 @@ NOT_SURE = "not_sure"
135
135
  NOT_TESTED = "not_tested"
136
136
  NO_EXAM = "NO_EXAM"
137
137
  NO_UNCONFIRMED = "no_unconfirmed"
138
+ NULL_STRING = ""
138
139
  OBSERVATION = "observation"
139
140
  OK = "OK"
140
141
  OFF_STUDY = "off study"
edc_crf/auths.py CHANGED
@@ -0,0 +1,5 @@
1
+ def update_site_auths():
2
+ return None
3
+
4
+
5
+ update_site_auths()
edc_dashboard/auths.py CHANGED
@@ -3,11 +3,15 @@ from edc_auth.utils import remove_default_model_permissions_from_edc_permissions
3
3
 
4
4
  from .auth_objects import dashboard_tuples
5
5
 
6
- site_auths.add_post_update_func(
7
- "edc_dashboard", remove_default_model_permissions_from_edc_permissions
8
- )
9
6
 
7
+ def update_site_auths():
8
+ site_auths.add_post_update_func(
9
+ "edc_dashboard", remove_default_model_permissions_from_edc_permissions
10
+ )
10
11
 
11
- site_auths.add_custom_permissions_tuples(
12
- model="edc_dashboard.edcpermissions", codename_tuples=dashboard_tuples
13
- )
12
+ site_auths.add_custom_permissions_tuples(
13
+ model="edc_dashboard.edcpermissions", codename_tuples=dashboard_tuples
14
+ )
15
+
16
+
17
+ update_site_auths()
@@ -20,12 +20,13 @@ if TYPE_CHECKING:
20
20
  class UrlConfig:
21
21
  def __init__(
22
22
  self,
23
- url_name: str = None,
24
- namespace: str = None,
25
- view_class: type[View | UrlRequestContextMixin] = None,
26
- label: str = None,
27
- identifier_label: str = None,
28
- identifier_pattern: str = None,
23
+ *,
24
+ url_name: str,
25
+ namespace: str,
26
+ view_class: type[View | UrlRequestContextMixin],
27
+ label: str,
28
+ identifier_label: str,
29
+ identifier_pattern: str,
29
30
  ):
30
31
  self.identifier_label = identifier_label
31
32
  self.identifier_pattern = identifier_pattern
@@ -39,102 +40,108 @@ class UrlConfig:
39
40
  @property
40
41
  def dashboard_urls(self) -> list[URLPattern]:
41
42
  """Returns url patterns."""
42
- urlpatterns = [
43
+ return [
43
44
  re_path(
44
- "%(label)s/"
45
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
45
+ "{label}/"
46
+ "(?P<{identifier_label}>{identifier_pattern})/"
46
47
  r"(?P<visit_schedule_name>\w+)/"
47
48
  r"(?P<schedule_name>\w+)/"
48
49
  r"(?P<visit_code>\w+)/"
49
- r"(?P<unscheduled>\w+)/"
50
- % {
51
- "label": self.label,
52
- "identifier_label": self.identifier_label,
53
- "identifier_pattern": self.identifier_pattern,
54
- },
50
+ r"(?P<unscheduled>\w+)/".format(
51
+ **dict(
52
+ label=self.label,
53
+ identifier_label=self.identifier_label,
54
+ identifier_pattern=self.identifier_pattern,
55
+ )
56
+ ),
55
57
  self.view_class.as_view(),
56
58
  name=self.url_name,
57
59
  ),
58
60
  re_path(
59
- "%(label)s/"
60
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
61
+ "{label}/"
62
+ "(?P<{identifier_label}>{identifier_pattern})/"
61
63
  r"(?P<visit_schedule_name>\w+)/"
62
64
  r"(?P<schedule_name>\w+)/"
63
- r"(?P<visit_code>\w+)/"
64
- % dict(
65
- label=self.label,
66
- identifier_label=self.identifier_label,
67
- identifier_pattern=self.identifier_pattern,
65
+ r"(?P<visit_code>\w+)/".format(
66
+ **dict(
67
+ label=self.label,
68
+ identifier_label=self.identifier_label,
69
+ identifier_pattern=self.identifier_pattern,
70
+ )
68
71
  ),
69
72
  self.view_class.as_view(),
70
73
  name=self.url_name,
71
74
  ),
72
75
  re_path(
73
- "%(label)s/"
74
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
75
- "(?P<appointment>%(uuid_pattern)s)/"
76
+ "{label}/"
77
+ "(?P<{identifier_label}>{identifier_pattern})/"
78
+ "(?P<appointment>{uuid_pattern})/"
76
79
  r"(?P<scanning>\d)/"
77
- r"(?P<error>\d)/"
78
- % dict(
79
- label=self.label,
80
- identifier_label=self.identifier_label,
81
- identifier_pattern=self.identifier_pattern,
82
- uuid_pattern=UUID_PATTERN.pattern,
80
+ r"(?P<error>\d)/".format(
81
+ **dict(
82
+ label=self.label,
83
+ identifier_label=self.identifier_label,
84
+ identifier_pattern=self.identifier_pattern,
85
+ uuid_pattern=UUID_PATTERN.pattern,
86
+ )
83
87
  ),
84
88
  self.view_class.as_view(),
85
89
  name=self.url_name,
86
90
  ),
87
91
  re_path(
88
- "%(label)s/"
89
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
90
- "(?P<appointment>%(uuid_pattern)s)/"
91
- r"(?P<reason>\w+)/"
92
- % dict(
93
- label=self.label,
94
- identifier_label=self.identifier_label,
95
- identifier_pattern=self.identifier_pattern,
96
- uuid_pattern=UUID_PATTERN.pattern,
92
+ "{label}/"
93
+ "(?P<{identifier_label}>{identifier_pattern})/"
94
+ "(?P<appointment>{uuid_pattern})/"
95
+ r"(?P<reason>\w+)/".format(
96
+ **dict(
97
+ label=self.label,
98
+ identifier_label=self.identifier_label,
99
+ identifier_pattern=self.identifier_pattern,
100
+ uuid_pattern=UUID_PATTERN.pattern,
101
+ )
97
102
  ),
98
103
  self.view_class.as_view(),
99
104
  name=self.url_name,
100
105
  ),
101
106
  re_path(
102
- "%(label)s/"
103
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
104
- "(?P<appointment>%(uuid_pattern)s)/"
105
- % dict(
106
- label=self.label,
107
- identifier_label=self.identifier_label,
108
- identifier_pattern=self.identifier_pattern,
109
- uuid_pattern=UUID_PATTERN.pattern,
107
+ "{label}/"
108
+ "(?P<{identifier_label}>{identifier_pattern})/"
109
+ "(?P<appointment>{uuid_pattern})/".format(
110
+ **dict(
111
+ label=self.label,
112
+ identifier_label=self.identifier_label,
113
+ identifier_pattern=self.identifier_pattern,
114
+ uuid_pattern=UUID_PATTERN.pattern,
115
+ )
110
116
  ),
111
117
  self.view_class.as_view(),
112
118
  name=self.url_name,
113
119
  ),
114
120
  re_path(
115
- "%(label)s/"
116
- "(?P<%(identifier_label)s>%(identifier_pattern)s)/"
117
- r"(?P<schedule_name>\w+)/"
118
- % dict(
119
- label=self.label,
120
- identifier_label=self.identifier_label,
121
- identifier_pattern=self.identifier_pattern,
121
+ "{label}/"
122
+ "(?P<{identifier_label}>{identifier_pattern})/"
123
+ r"(?P<schedule_name>\w+)/".format(
124
+ **dict(
125
+ label=self.label,
126
+ identifier_label=self.identifier_label,
127
+ identifier_pattern=self.identifier_pattern,
128
+ )
122
129
  ),
123
130
  self.view_class.as_view(),
124
131
  name=self.url_name,
125
132
  ),
126
133
  re_path(
127
- "%(label)s/(?P<%(identifier_label)s>%(identifier_pattern)s)/"
128
- % dict(
129
- label=self.label,
130
- identifier_label=self.identifier_label,
131
- identifier_pattern=self.identifier_pattern,
134
+ "{label}/(?P<{identifier_label}>{identifier_pattern})/".format(
135
+ **dict(
136
+ label=self.label,
137
+ identifier_label=self.identifier_label,
138
+ identifier_pattern=self.identifier_pattern,
139
+ )
132
140
  ),
133
141
  self.view_class.as_view(),
134
142
  name=self.url_name,
135
143
  ),
136
144
  ]
137
- return urlpatterns
138
145
 
139
146
  @property
140
147
  def listboard_urls(self) -> list[URLPattern]:
@@ -142,52 +149,54 @@ class UrlConfig:
142
149
 
143
150
  configs = [(listboard_url, listboard_view_class, label), (), ...]
144
151
  """
145
- urlpatterns = [
152
+ return [
146
153
  re_path(
147
- "%(label)s/(?P<%(identifier_label)s>%(identifier_pattern)s)/"
148
- r"(?P<page>\d+)/"
149
- % dict(
150
- label=self.label,
151
- identifier_label=self.identifier_label,
152
- identifier_pattern=self.identifier_pattern,
154
+ "{label}/(?P<{identifier_label}>{identifier_pattern})/"
155
+ r"(?P<page>\d+)/".format(
156
+ **dict(
157
+ label=self.label,
158
+ identifier_label=self.identifier_label,
159
+ identifier_pattern=self.identifier_pattern,
160
+ )
153
161
  ),
154
162
  self.view_class.as_view(),
155
163
  name=self.url_name,
156
164
  ),
157
165
  re_path(
158
- "%(label)s/(?P<%(identifier_label)s>%(identifier_pattern)s)/"
159
- % dict(
160
- label=self.label,
161
- identifier_label=self.identifier_label,
162
- identifier_pattern=self.identifier_pattern,
166
+ "{label}/(?P<{identifier_label}>{identifier_pattern})/".format(
167
+ **dict(
168
+ label=self.label,
169
+ identifier_label=self.identifier_label,
170
+ identifier_pattern=self.identifier_pattern,
171
+ )
163
172
  ),
164
173
  self.view_class.as_view(),
165
174
  name=self.url_name,
166
175
  ),
167
176
  re_path(
168
- r"%(label)s/(?P<page>\d+)/" % dict(label=self.label),
177
+ r"{label}/(?P<page>\d+)/".format(**dict(label=self.label)),
169
178
  self.view_class.as_view(),
170
179
  name=self.url_name,
171
180
  ),
172
181
  re_path(
173
- r"%(label)s/" % dict(label=self.label),
182
+ r"{label}/".format(**dict(label=self.label)),
174
183
  self.view_class.as_view(),
175
184
  name=self.url_name,
176
185
  ),
177
186
  ]
178
- return urlpatterns
179
187
 
180
188
  @property
181
189
  def review_listboard_urls(self) -> list[URLPattern]:
182
190
  url_patterns = [
183
191
  re_path(
184
- "%(label)s/(?P<%(identifier_label)s>%(identifier_pattern)s)/"
185
- "(?P<appointment>%(uuid_pattern)s)/"
186
- % dict(
187
- label=self.label,
188
- identifier_label=self.identifier_label,
189
- identifier_pattern=self.identifier_pattern,
190
- uuid_pattern=UUID_PATTERN.pattern,
192
+ "{label}/(?P<{identifier_label}>{identifier_pattern})/"
193
+ "(?P<appointment>{uuid_pattern})/".format(
194
+ **dict(
195
+ label=self.label,
196
+ identifier_label=self.identifier_label,
197
+ identifier_pattern=self.identifier_pattern,
198
+ uuid_pattern=UUID_PATTERN.pattern,
199
+ )
191
200
  ),
192
201
  self.view_class.as_view(),
193
202
  name=self.url_name,
@@ -3,11 +3,11 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
 
5
5
 
6
- class AlreadyRegistered(Exception):
6
+ class AlreadyRegistered(Exception): # noqa: N818
7
7
  pass
8
8
 
9
9
 
10
- class InvalidDashboardUrlName(Exception):
10
+ class InvalidDashboardUrlName(Exception): # noqa: N818
11
11
  pass
12
12
 
13
13
 
@@ -16,12 +16,12 @@ class UrlNames:
16
16
  registry: dict[str, str] = field(default_factory=dict)
17
17
 
18
18
  def register(
19
- self, name: str = None, url: str = None, namespace: str | None = None
19
+ self, name: str | None = None, url: str | None = None, namespace: str | None = None
20
20
  ) -> None:
21
21
  name = name or url
22
22
  complete_url = f"{namespace}:{url}" if namespace else url
23
23
  if name in self.registry:
24
- raise AlreadyRegistered(f"Url already registered. Got {name}.")
24
+ raise AlreadyRegistered(f"Url already registered. Got {complete_url}.")
25
25
  self.registry.update({name: complete_url})
26
26
 
27
27
  def register_from_dict(self, **urldata: str) -> None:
@@ -30,10 +30,11 @@ class UrlRequestContextMixin:
30
30
  @classmethod
31
31
  def urls(
32
32
  cls,
33
- namespace: str = None,
34
- label: str = None,
35
- identifier_label: str = None,
36
- identifier_pattern: str = None,
33
+ *,
34
+ label: str,
35
+ identifier_pattern: str,
36
+ namespace: str | None = None,
37
+ identifier_label: str | None = None,
37
38
  ) -> list[URLPattern]:
38
39
  label = (
39
40
  label
@@ -62,5 +63,5 @@ class UrlRequestContextMixin:
62
63
  f"Url name not defined in url_names. "
63
64
  f"Expected one of {url_names.registry}. Got {e}. "
64
65
  f"Hint: check if dashboard middleware is loaded."
65
- )
66
+ ) from e
66
67
  return url_data
@@ -45,7 +45,7 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
45
45
 
46
46
  locked_column_template_name = "edc_data_manager/columns/locked.html"
47
47
 
48
- status_column_context = {
48
+ status_column_context = { # noqa: RUF012
49
49
  "NEW": NEW,
50
50
  "OPEN": OPEN,
51
51
  "FEEDBACK": FEEDBACK,
@@ -61,13 +61,13 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
61
61
 
62
62
  actions = (toggle_dm_status,)
63
63
 
64
- radio_fields = {
64
+ radio_fields = { # noqa: RUF012
65
65
  "status": admin.VERTICAL,
66
66
  "site_response_status": admin.VERTICAL,
67
67
  "query_priority": admin.VERTICAL,
68
68
  }
69
69
 
70
- autocomplete_fields = [
70
+ autocomplete_fields = (
71
71
  "sender",
72
72
  "recipients",
73
73
  "data_dictionaries",
@@ -75,7 +75,7 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
75
75
  "visit_schedule",
76
76
  "registered_subject",
77
77
  "dm_user",
78
- ]
78
+ )
79
79
 
80
80
  list_display = (
81
81
  "wrapped_title",
@@ -201,11 +201,10 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
201
201
  wrapped_title.short_description = "Title"
202
202
 
203
203
  def formfield_for_manytomany(self, db_field, request, **kwargs):
204
- if db_field.name == "data_dictionaries":
205
- if request.GET.get("title"):
206
- kwargs["queryset"] = DataDictionary.objects.filter(
207
- model_verbose_name=request.GET.get("title")
208
- )
204
+ if db_field.name == "data_dictionaries" and request.GET.get("title"):
205
+ kwargs["queryset"] = DataDictionary.objects.filter(
206
+ model_verbose_name=request.GET.get("title")
207
+ )
209
208
  return super().formfield_for_manytomany(db_field, request, **kwargs)
210
209
 
211
210
  def query_dates(self, obj):
@@ -332,7 +331,8 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
332
331
  "missed_visit",
333
332
  "auto_resolved",
334
333
  "registered_subject",
335
- ) + action_fields
334
+ *action_fields,
335
+ )
336
336
  if not request.user.groups.filter(name=DATA_MANAGER):
337
337
  extra_fields = (
338
338
  "data_dictionaries",
@@ -350,10 +350,11 @@ class DataQueryAdmin(SiteModelAdminMixin, ModelAdminSubjectDashboardMixin, Simpl
350
350
  "title",
351
351
  "visit_code_sequence",
352
352
  "visit_schedule",
353
+ *extra_fields,
353
354
  )
354
355
  if not obj:
355
356
  extra_fields = tuple(f for f in extra_fields if f != "registered_subject")
356
- return fields + extra_fields
357
+ return *fields, *extra_fields
357
358
 
358
359
  def get_subject_dashboard_url_kwargs(self, obj):
359
360
  def get_opts():
edc_data_manager/auths.py CHANGED
@@ -18,45 +18,48 @@ from .auth_objects import (
18
18
  data_manager,
19
19
  )
20
20
 
21
- site_auths.add_custom_permissions_tuples(
22
- model="edc_data_manager.edcpermissions", codename_tuples=custom_codename_tuples
23
- )
24
21
 
25
- site_auths.add_custom_permissions_tuples(
26
- model="edc_data_manager.edcpermissions",
27
- codename_tuples=[("edc_data_manager.special_bypassmodelform", "Can bypass modelform")],
28
- )
22
+ def update_site_auths():
23
+ site_auths.add_custom_permissions_tuples(
24
+ model="edc_data_manager.edcpermissions", codename_tuples=custom_codename_tuples
25
+ )
29
26
 
27
+ site_auths.add_custom_permissions_tuples(
28
+ model="edc_data_manager.edcpermissions",
29
+ codename_tuples=[("edc_data_manager.special_bypassmodelform", "Can bypass modelform")],
30
+ )
30
31
 
31
- # groups
32
- site_auths.add_group(*data_manager, name=DATA_MANAGER)
33
- site_auths.add_group(*data_manager, name=DATA_QUERY_VIEW, view_only=True)
32
+ # groups
33
+ site_auths.add_group(*data_manager, name=DATA_MANAGER)
34
+ site_auths.add_group(*data_manager, name=DATA_QUERY_VIEW, view_only=True)
34
35
 
35
- site_auths.add_group(*data_manager, name=DATA_QUERY, view_only=True)
36
- site_auths.update_group("edc_data_manager.change_dataquery", name=DATA_QUERY)
36
+ site_auths.add_group(*data_manager, name=DATA_QUERY, view_only=True)
37
+ site_auths.update_group("edc_data_manager.change_dataquery", name=DATA_QUERY)
37
38
 
38
- site_auths.add_group(
39
- "edc_data_manager.export_datadictionary",
40
- "edc_data_manager.export_dataquery",
41
- "edc_data_manager.export_queryrule",
42
- name=DATA_MANAGER_EXPORT,
43
- )
39
+ site_auths.add_group(
40
+ "edc_data_manager.export_datadictionary",
41
+ "edc_data_manager.export_dataquery",
42
+ "edc_data_manager.export_queryrule",
43
+ name=DATA_MANAGER_EXPORT,
44
+ )
44
45
 
45
- site_auths.add_group(*data_manager, name=DATA_MANAGER_SUPER)
46
- site_auths.update_group("edc_data_manager.change_dataquery", name=DATA_MANAGER_SUPER)
47
- site_auths.update_group(
48
- "edc_data_manager.export_datadictionary",
49
- "edc_data_manager.export_dataquery",
50
- "edc_data_manager.export_queryrule",
51
- "edc_data_manager.special_bypassmodelform",
52
- "edc_data_manager.change_dataquery",
53
- name=DATA_MANAGER_SUPER,
54
- )
46
+ site_auths.add_group(*data_manager, name=DATA_MANAGER_SUPER)
47
+ site_auths.update_group("edc_data_manager.change_dataquery", name=DATA_MANAGER_SUPER)
48
+ site_auths.update_group(
49
+ "edc_data_manager.export_datadictionary",
50
+ "edc_data_manager.export_dataquery",
51
+ "edc_data_manager.export_queryrule",
52
+ "edc_data_manager.special_bypassmodelform",
53
+ "edc_data_manager.change_dataquery",
54
+ name=DATA_MANAGER_SUPER,
55
+ )
56
+
57
+ # roles
58
+ site_auths.add_role(CELERY_MANAGER, DATA_MANAGER, name=DATA_MANAGER_ROLE)
59
+ site_auths.add_role(DATA_QUERY, name=SITE_DATA_MANAGER_ROLE)
60
+ site_auths.update_role(DATA_QUERY, name=CLINICIAN_ROLE)
61
+ site_auths.update_role(DATA_QUERY, name=NURSE_ROLE)
62
+ site_auths.update_role(DATA_QUERY, name=CLINICIAN_SUPER_ROLE)
55
63
 
56
64
 
57
- # roles
58
- site_auths.add_role(CELERY_MANAGER, DATA_MANAGER, name=DATA_MANAGER_ROLE)
59
- site_auths.add_role(DATA_QUERY, name=SITE_DATA_MANAGER_ROLE)
60
- site_auths.update_role(DATA_QUERY, name=CLINICIAN_ROLE)
61
- site_auths.update_role(DATA_QUERY, name=NURSE_ROLE)
62
- site_auths.update_role(DATA_QUERY, name=CLINICIAN_SUPER_ROLE)
65
+ update_site_auths()
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
4
  from decimal import Decimal
5
- from typing import TYPE_CHECKING, LiteralString
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from tqdm import tqdm
8
8
 
@@ -17,12 +17,12 @@ if TYPE_CHECKING:
17
17
  class QueryRuleWrapper:
18
18
  def __init__(
19
19
  self,
20
- query_rule_obj: QueryRule = None,
21
- subject_identifiers: list[LiteralString] = None,
22
- visit_schedule_obj: QueryVisitSchedule = None,
23
- timepoint: Decimal = None,
24
- entry_status: str = None,
25
- now: datetime = None,
20
+ query_rule_obj: QueryRule | None = None,
21
+ subject_identifiers: list[str] | None = None,
22
+ visit_schedule_obj: QueryVisitSchedule | None = None,
23
+ timepoint: Decimal | None = None,
24
+ entry_status: str | None = None,
25
+ now: datetime | None = None,
26
26
  verbose: bool | None = None,
27
27
  ):
28
28
  self.now = now
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from tempfile import mkdtemp
4
5
  from typing import TYPE_CHECKING
5
6
 
@@ -17,7 +18,7 @@ if TYPE_CHECKING:
17
18
  from django.contrib.auth.models import User
18
19
 
19
20
 
20
- class ArchiveExporterNothingExported(Exception):
21
+ class ArchiveExporterNothingExported(Exception): # noqa: N818
21
22
  pass
22
23
 
23
24
 
@@ -56,7 +57,7 @@ class ArchiveExporter:
56
57
  for model in models:
57
58
  csv_exporter = self.csv_exporter_cls(
58
59
  model=model,
59
- export_folder=tmp_folder,
60
+ export_folder=Path(tmp_folder),
60
61
  decrypt=decrypt,
61
62
  site_ids=sites.get_site_ids_for_user(
62
63
  user=user, site_id=sites.get_current_site().site_id