clinicedc 2.0.28__py3-none-any.whl → 2.0.30__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 (98) hide show
  1. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/RECORD +98 -98
  3. edc_auth/admin/fieldsets.py +11 -15
  4. edc_auth/admin/group_admin.py +2 -5
  5. edc_auth/admin/list_filters.py +8 -7
  6. edc_auth/admin/role_admin.py +7 -10
  7. edc_auth/admin/user_admin.py +2 -2
  8. edc_auth/admin/user_profile_admin.py +3 -7
  9. edc_auth/apps.py +2 -2
  10. edc_auth/auth_updater/group_updater.py +4 -4
  11. edc_auth/auth_updater/role_updater.py +1 -3
  12. edc_auth/backends.py +1 -1
  13. edc_auth/export_users.py +6 -5
  14. edc_auth/fix_export_permissions.py +8 -8
  15. edc_auth/forms.py +21 -24
  16. edc_auth/get_app_codenames.py +2 -2
  17. edc_auth/import_users.py +25 -24
  18. edc_auth/management/commands/export_users.py +1 -1
  19. edc_auth/management/commands/fix_export_permissions.py +1 -1
  20. edc_auth/management/commands/import_users.py +1 -1
  21. edc_auth/management/commands/reset_password.py +2 -2
  22. edc_auth/models/signals.py +1 -1
  23. edc_auth/models/user_profile.py +4 -5
  24. edc_auth/password_setter.py +4 -4
  25. edc_auth/post_migrate_signals.py +2 -2
  26. edc_auth/send_new_credentials_to_user.py +1 -1
  27. edc_auth/system_checks.py +7 -6
  28. edc_auth/utils.py +10 -12
  29. edc_consent/consent_definition.py +4 -1
  30. edc_dashboard/view_mixins/edc_view_mixin.py +1 -1
  31. edc_model_admin/mixins/model_admin_form_instructions_mixin.py +9 -3
  32. edc_model_admin/mixins/model_admin_next_url_redirect_mixin.py +3 -3
  33. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +7 -7
  34. edc_model_admin/mixins/model_admin_redirect_on_delete_mixin.py +6 -8
  35. edc_pharmacy/admin_mixin.py +1 -1
  36. edc_pharmacy/approve_prescription.py +10 -8
  37. edc_pharmacy/auth_objects.py +1 -1
  38. edc_pharmacy/exceptions.py +7 -7
  39. edc_pharmacy/settings.py +1 -1
  40. edc_pharmacy/views/add_to_storage_bin_view.py +22 -24
  41. edc_pharmacy/views/allocate_to_subject_view.py +10 -18
  42. edc_pharmacy/views/celery_task_status_view.py +1 -2
  43. edc_pharmacy/views/confirm_stock_from_instance_view.py +1 -1
  44. edc_pharmacy/views/confirm_stock_from_queryset_view.py +5 -8
  45. edc_pharmacy/views/dispense_view.py +1 -1
  46. edc_pharmacy/views/move_to_storage_bin_view.py +7 -3
  47. edc_pharmacy/views/prepare_and_review_stock_request_view.py +62 -70
  48. edc_pharmacy/views/print_labels_view.py +1 -1
  49. edc_pharmacy/views/transfer_stock_view.py +1 -1
  50. edc_prn/modelform_mixins.py +8 -9
  51. edc_prn/models.py +3 -1
  52. edc_prn/site_prn_forms.py +2 -2
  53. edc_prn/templatetags/edc_prn_extras.py +1 -1
  54. edc_protocol/middleware.py +1 -1
  55. edc_protocol/research_protocol_config.py +7 -5
  56. edc_protocol_incident/admin/protocol_deviation_violation_admin.py +1 -1
  57. edc_protocol_incident/form_validators/mixins.py +9 -6
  58. edc_protocol_incident/modeladmin_mixins.py +1 -1
  59. edc_pylabels/admin/label_configuration_admin.py +1 -1
  60. edc_pylabels/admin/label_specification_admin.py +1 -1
  61. edc_pylabels/auth_objects.py +1 -1
  62. edc_pylabels/site_label_configs.py +2 -2
  63. edc_qareports/admin/qa_report_log_admin.py +5 -5
  64. edc_qareports/admin/qa_report_log_summary_admin.py +1 -1
  65. edc_qareports/forms/note_form.py +2 -3
  66. edc_qareports/modeladmin_mixins/list_filters.py +23 -19
  67. edc_qareports/modeladmin_mixins/note_modeladmin_mixin.py +7 -7
  68. edc_qareports/modeladmin_mixins/on_study_missing_values_modeladmin_mixin.py +8 -8
  69. edc_qareports/modeladmin_mixins/qa_report_modeladmin_mixin.py +3 -7
  70. edc_qareports/sql_generator/crf_case.py +1 -1
  71. edc_qareports/sql_generator/crf_subquery.py +1 -1
  72. edc_qareports/sql_generator/requisition_subquery.py +1 -1
  73. edc_qareports/sql_generator/sql_view_generator.py +1 -1
  74. edc_qareports/sql_generator/subquery_from_dict.py +39 -39
  75. edc_qareports/utils.py +12 -13
  76. edc_randomization/model_mixins.py +1 -1
  77. edc_randomization/system_checks.py +1 -1
  78. edc_refusal/admin.py +4 -2
  79. edc_registration/modeladmin_mixins.py +18 -20
  80. edc_registration/modelform_mixins.py +2 -2
  81. edc_registration/models/signals.py +1 -1
  82. edc_registration/utils.py +1 -1
  83. edc_reportable/age_evaluator.py +4 -4
  84. edc_reportable/data/grading_data/daids_july_2017.py +3 -3
  85. edc_reportable/evaluator.py +15 -15
  86. edc_reportable/exceptions.py +4 -4
  87. edc_reportable/forms/reportables_form_validator_mixin.py +6 -2
  88. edc_reportable/management/commands/export_reportables.py +1 -1
  89. edc_reportable/models/grading_exception.py +1 -6
  90. edc_reportable/models/normal_data.py +3 -3
  91. edc_reportable/models/reference_range_collection.py +1 -6
  92. edc_reportable/utils/get_grade_for_value.py +15 -15
  93. edc_reportable/utils/get_normal_data_or_raise.py +14 -14
  94. edc_reportable/utils/in_normal_bounds_or_raise.py +6 -6
  95. edc_reportable/utils/load_data.py +1 -1
  96. edc_reportable/utils/update_grading_exceptions.py +5 -5
  97. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/WHEEL +0 -0
  98. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,4 @@
1
1
  from django.contrib import admin
2
- from django.utils.html import format_html
3
2
  from django.utils.safestring import mark_safe
4
3
 
5
4
  from edc_model_admin.mixins import TemplatesModelAdminMixin
@@ -12,22 +11,20 @@ from ..models import Role
12
11
  class RoleAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
13
12
  fieldsets = ((None, ({"fields": ("display_name", "name", "display_index", "groups")})),)
14
13
 
15
- list_display_links: tuple[str, ...] = ("display_name", "group_list")
14
+ list_display_links = ("display_name", "group_list")
16
15
 
17
- list_display: tuple[str, ...] = ("display_name", "name", "group_list")
16
+ list_display = ("display_name", "name", "group_list")
18
17
 
19
- filter_horizontal: tuple[str, ...] = ("groups",)
18
+ filter_horizontal = ("groups",)
20
19
 
21
- search_fields: tuple[str, ...] = ("display_name", "name", "groups__name")
20
+ search_fields = ("display_name", "name", "groups__name")
22
21
 
23
- ordering: tuple[str, ...] = ("display_index", "display_name")
22
+ ordering = ("display_index", "display_name")
24
23
 
25
24
  list_filter = ("groups__name",)
26
25
 
27
26
  @staticmethod
28
27
  def group_list(obj=None) -> str:
29
- group_names = []
30
- for group in obj.groups.all():
31
- group_names.append(group.name)
28
+ group_names = [group.name for group in obj.groups.all()]
32
29
  group_names.sort()
33
- return format_html("{}", mark_safe("<BR>".join(group_names))) # nosec B703 B308
30
+ return mark_safe("<BR>".join(group_names)) # noqa: S308
@@ -31,8 +31,8 @@ class UserAdmin(TemplatesModelAdminMixin, BaseUserAdmin):
31
31
  show_object_tools: bool = True
32
32
 
33
33
  form = UserChangeForm
34
- inlines = [UserProfileInline]
35
- actions = [send_new_credentials_to_user_action]
34
+ inlines = (UserProfileInline,)
35
+ actions = (send_new_credentials_to_user_action,)
36
36
 
37
37
  list_display = (
38
38
  "username",
@@ -1,5 +1,4 @@
1
1
  from django.contrib import admin
2
- from django.utils.html import format_html
3
2
  from django.utils.safestring import mark_safe
4
3
 
5
4
  from edc_model_admin.mixins import TemplatesModelAdminMixin
@@ -45,21 +44,18 @@ class UserProfileAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
45
44
  @staticmethod
46
45
  def user_sites(obj=None):
47
46
  site_names = [o.name for o in obj.sites.all().order_by("name")]
48
- return format_html("{}", mark_safe("<BR>".join(site_names))) # nosec B703 B308
47
+ return mark_safe("<BR>".join(site_names)) # noqa: S308
49
48
 
50
49
  @staticmethod
51
50
  def user_email_notifications(obj=None):
52
51
  display_names = [
53
52
  o.display_name for o in obj.email_notifications.all().order_by("display_name")
54
53
  ]
55
- return format_html("{}", mark_safe("<BR>".join(display_names))) # nosec B703 B308
54
+ return mark_safe("<BR>".join(display_names)) # noqa: S308
56
55
 
57
56
  @staticmethod
58
57
  def user_sms_notifications(obj=None):
59
58
  display_names = [
60
59
  o.display_name for o in obj.sms_notifications.all().order_by("display_name")
61
60
  ]
62
- return format_html(
63
- "{}",
64
- mark_safe("<BR>".join(display_names)), # nosec B703, B308
65
- )
61
+ return mark_safe("<BR>".join(display_names)) # noqa: S308
edc_auth/apps.py CHANGED
@@ -11,9 +11,9 @@ class AppConfig(DjangoAppConfig):
11
11
  default_auto_field = "django.db.models.BigAutoField"
12
12
 
13
13
  def ready(self):
14
- from edc_appconfig.system_checks import check_for_edc_appconfig
14
+ from edc_appconfig.system_checks import check_for_edc_appconfig # noqa: PLC0415
15
15
 
16
- from .system_checks import (
16
+ from .system_checks import ( # noqa: PLC0415
17
17
  check_auth_updater,
18
18
  check_etc_dir,
19
19
  check_site_auths,
@@ -139,7 +139,7 @@ class GroupUpdater:
139
139
  errmsg = f"{e} Got codename={codename},app_label={app_label}"
140
140
  if not self.warn_only:
141
141
  raise CodenameDoesNotExist(errmsg) from e
142
- warn(style.ERROR(errmsg))
142
+ warn(style.ERROR(errmsg), stacklevel=2)
143
143
  except MultipleObjectsReturned as e:
144
144
  if not allow_multiple_objects:
145
145
  self.delete_and_raise_on_duplicate_codenames(
@@ -219,7 +219,7 @@ class GroupUpdater:
219
219
  try:
220
220
  model_cls = self.apps.get_model(model)
221
221
  except LookupError as e:
222
- warn(f"{e}. Got {model}")
222
+ warn(f"{e}. Got {model}", stacklevel=2)
223
223
  else:
224
224
  content_type = self.content_type_model_cls.objects.get_for_model(model_cls)
225
225
  for codename_tpl in codename_tuples:
@@ -282,8 +282,8 @@ class GroupUpdater:
282
282
 
283
283
  def remove_permissions_by_codenames(
284
284
  self,
285
- group: Any = None,
286
- codenames: list[str] = None,
285
+ group,
286
+ codenames: list[str],
287
287
  allow_multiple_objects: bool | None = None,
288
288
  ):
289
289
  """Remove the given codenames from the given group."""
@@ -36,8 +36,7 @@ class RoleUpdater:
36
36
  """
37
37
  if self.verbose:
38
38
  sys.stdout.write(style.MIGRATE_HEADING(" - Updating roles:\n"))
39
- index = 0
40
- for role_name, groups in self.roles.items():
39
+ for index, (role_name, groups) in enumerate(self.roles.items()):
41
40
  display_name = role_name.replace("_", " ").lower().title()
42
41
  if self.verbose:
43
42
  sys.stdout.write(f" * updating groups for {role_name}.\n")
@@ -63,7 +62,6 @@ class RoleUpdater:
63
62
  ) from e
64
63
  # group = self.group_model_cls.objects.create(name=group_name)
65
64
  role.groups.add(group)
66
- index += 1
67
65
  if self.verbose:
68
66
  sys.stdout.write(" Done.\n")
69
67
  sys.stdout.flush()
edc_auth/backends.py CHANGED
@@ -10,7 +10,7 @@ class ModelBackendWithSite(ModelBackend):
10
10
  associated with the current SITE_ID.
11
11
  """
12
12
 
13
- def authenticate(self, request, username=None, password=None, **kwargs):
13
+ def authenticate(self, request, username=None, password=None, **kwargs): # noqa: ARG002
14
14
  user = super().authenticate(request, username=username, password=password)
15
15
  if user:
16
16
  sites = [obj.id for obj in user.userprofile.sites.all()]
edc_auth/export_users.py CHANGED
@@ -1,11 +1,12 @@
1
1
  import csv
2
- from datetime import datetime
2
+ from pathlib import Path
3
3
 
4
4
  from django.contrib.auth.models import User
5
+ from django.utils import timezone
5
6
 
6
7
 
7
8
  def export_users(path):
8
- path = path or f"edc_users_{datetime.now().strftime('%Y%m%d%H%M%S')}.csv"
9
+ path = path or f"edc_users_{timezone.now().strftime('%Y%m%d%H%M%S')}.csv"
9
10
  user = {
10
11
  "username": None,
11
12
  "password": None,
@@ -21,13 +22,13 @@ def export_users(path):
21
22
  "role_names": None,
22
23
  }
23
24
 
24
- with open(path, "w+") as f:
25
+ with Path(path).open("w+") as f:
25
26
  writer = csv.DictWriter(f, fieldnames=user, delimiter="|")
26
27
  writer.writeheader()
27
28
  for user in User.objects.all().order_by("username"):
28
29
  site_names = ",".join([s.name for s in user.userprofile.sites.all()])
29
30
  role_names = ",".join([g.name for g in user.userprofile.roles.all()])
30
- user = {
31
+ user = { # noqa: PLW2901
31
32
  "username": user.username,
32
33
  "password": user.password,
33
34
  "is_staff": user.is_staff,
@@ -42,4 +43,4 @@ def export_users(path):
42
43
  "role_names": role_names or "",
43
44
  }
44
45
  writer.writerow(user)
45
- print(f"Done. See file `{path}` in the current directory.")
46
+ print(f"Done. See file `{path}` in the current directory.") # noqa: T201
@@ -33,23 +33,23 @@ class ExportPermissionsFixer:
33
33
  """
34
34
 
35
35
  if self.verbose:
36
- print("Adding `import` and `export` to default permissions.")
36
+ print("Adding `import` and `export` to default permissions.") # noqa: T201
37
37
  for app_config in self.app_configs:
38
38
  if self.verbose:
39
- print(f" * updating {app_config.name}")
39
+ print(f" * updating {app_config.name}") # noqa: T201
40
40
  for model in app_config.get_models():
41
41
  self.fix_for_model(model)
42
42
  if self.verbose:
43
- print("Done")
43
+ print("Done") # noqa: T201
44
44
 
45
45
  def fix_for_model(self, model):
46
- from edc_model import models as edc_models
46
+ from edc_model import models as edc_models # noqa: PLC0415
47
47
 
48
48
  if issubclass(model, (edc_models.BaseUuidModel,)):
49
49
  permission_model_cls = django_apps.get_model("auth.permission")
50
50
  content_type_model_cls = django_apps.get_model("contenttypes.contenttype")
51
51
  if self.verbose:
52
- print(f" - {model._meta.label_lower}")
52
+ print(f" - {model._meta.label_lower}") # noqa: T201
53
53
  try:
54
54
  app_label, model_name = model._meta.label_lower.split(".")
55
55
  content_type = content_type_model_cls.objects.get(
@@ -58,9 +58,9 @@ class ExportPermissionsFixer:
58
58
  )
59
59
  except ObjectDoesNotExist as e:
60
60
  if self.warn_only:
61
- warn(f"ObjectDoesNotExist: {e} Got {model}.")
61
+ warn(f"ObjectDoesNotExist: {e} Got {model}.", stacklevel=2)
62
62
  else:
63
- raise ObjectDoesNotExist(f"{e} Got {model}.")
63
+ raise ObjectDoesNotExist(f"{e} Got {model}.") from e
64
64
  else:
65
65
  for action in ["import", "export"]:
66
66
  codename = f"{action}_{model._meta.label_lower.split('.')[1]}"
@@ -71,7 +71,7 @@ class ExportPermissionsFixer:
71
71
  opts.update(name=f"Can {action} {model._meta.verbose_name}")
72
72
  permission_model_cls.objects.create(**opts)
73
73
  if self.verbose:
74
- print(f" created for {model._meta.label_lower}")
74
+ print(f" created for {model._meta.label_lower}") # noqa: T201
75
75
  else:
76
76
  obj.name = f"Can {action} {model._meta.verbose_name}"
77
77
  obj.save()
edc_auth/forms.py CHANGED
@@ -45,36 +45,33 @@ class UserProfileForm(forms.ModelForm):
45
45
  raise forms.ValidationError(
46
46
  {
47
47
  "is_multisite_viewer": (
48
- "Invalid. User has change permissions to other objects. "
49
- f"Got {c}"
48
+ f"Invalid. User has change permissions to other objects. Got {c}"
50
49
  )
51
50
  }
52
51
  )
53
52
 
54
53
  qs = self.cleaned_data.get("email_notifications")
55
- if qs and qs.count() > 0:
56
- if not get_email_enabled():
57
- raise forms.ValidationError(
58
- {
59
- "email_notifications": (
60
- "You may not choose an email "
61
- "notification. Email is not enabled. "
62
- "Contact your EDC administrator."
63
- )
64
- }
65
- )
54
+ if qs and qs.count() > 0 and not get_email_enabled():
55
+ raise forms.ValidationError(
56
+ {
57
+ "email_notifications": (
58
+ "You may not choose an email "
59
+ "notification. Email is not enabled. "
60
+ "Contact your EDC administrator."
61
+ )
62
+ }
63
+ )
66
64
  qs = self.cleaned_data.get("sms_notifications")
67
- if qs and qs.count() > 0:
68
- if not settings.TWILIO_ENABLED:
69
- raise forms.ValidationError(
70
- {
71
- "sms_notifications": (
72
- "You may not choose an SMS "
73
- "notification. SMS is not enabled. "
74
- "Contact your EDC administrator."
75
- )
76
- }
77
- )
65
+ if qs and qs.count() > 0 and not settings.TWILIO_ENABLED:
66
+ raise forms.ValidationError(
67
+ {
68
+ "sms_notifications": (
69
+ "You may not choose an SMS "
70
+ "notification. SMS is not enabled. "
71
+ "Contact your EDC administrator."
72
+ )
73
+ }
74
+ )
78
75
  qs = self.cleaned_data.get("roles")
79
76
  if qs and qs.count() > 0:
80
77
  for role in qs:
@@ -38,7 +38,7 @@ def get_app_codenames(
38
38
  pass
39
39
  else:
40
40
  for model_cls in get_models(app_config, exclude_models):
41
- codenames.append(f"{app_config.name}.view_{model_cls._meta.model_name}")
41
+ codenames.append(f"{app_config.name}.view_{model_cls._meta.model_name}") # noqa: PERF401
42
42
  for name in crud_apps:
43
43
  try:
44
44
  app_config = django_apps.get_app_config(name)
@@ -80,5 +80,5 @@ def get_codename(
80
80
  ]
81
81
  prefixes = [f"{s}_" for s in permissions]
82
82
  for prefix in prefixes:
83
- codenames.append(f"{app_name}.{prefix}{model_name}")
83
+ codenames.append(f"{app_name}.{prefix}{model_name}") # noqa: PERF401
84
84
  return codenames
edc_auth/import_users.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import csv
2
- import os
3
2
  import re
4
- from datetime import datetime
3
+ import sys
4
+ from pathlib import Path
5
5
  from string import Template
6
6
  from typing import Any
7
7
 
@@ -9,6 +9,7 @@ from django.contrib.auth.models import User
9
9
  from django.contrib.sites.models import Site
10
10
  from django.core.exceptions import ObjectDoesNotExist
11
11
  from django.core.mail import EmailMessage
12
+ from django.utils import timezone
12
13
  from mempass import PasswordGenerator
13
14
 
14
15
  from edc_protocol.research_protocol_config import ResearchProtocolConfig
@@ -89,8 +90,8 @@ def import_users(
89
90
  site_names: a comma-separated list of sites
90
91
  role_names: a comma-separated list of roles
91
92
  """
92
- path = os.path.expanduser(path)
93
- with open(path) as f:
93
+ path = Path(path)
94
+ with path.open() as f:
94
95
  reader = csv.DictReader(f, delimiter="|")
95
96
  for csv_data in reader:
96
97
  opts: dict = {}
@@ -111,8 +112,8 @@ def import_users(
111
112
  opts.update(email=csv_data.get("email"))
112
113
  opts.update(alternate_email=csv_data.get("alternate_email"))
113
114
  opts.update(job_title=csv_data.get("job_title"))
114
- opts.update(is_active=True if csv_data.get("is_active") == "True" else False)
115
- opts.update(is_staff=True if csv_data.get("is_staff") == "True" else False)
115
+ opts.update(is_active=csv_data.get("is_active") == "True")
116
+ opts.update(is_staff=csv_data.get("is_staff") == "True")
116
117
  UserImporter(
117
118
  resource_name=resource_name,
118
119
  send_email_to_user=send_email_to_user,
@@ -122,7 +123,7 @@ def import_users(
122
123
  **kwargs,
123
124
  )
124
125
  if export_to_file:
125
- export_users(f"edc_users_imported_{datetime.now().strftime('%Y%m%d%H%M%S')}")
126
+ export_users(f"edc_users_imported_{timezone.now().strftime('%Y%m%d%H%M%S')}")
126
127
 
127
128
 
128
129
  class UserImporter:
@@ -133,18 +134,18 @@ class UserImporter:
133
134
 
134
135
  def __init__(
135
136
  self,
136
- username: str = None,
137
- first_name: str = None,
138
- last_name: str = None,
139
- job_title: str = None,
140
- email: str = None,
141
- alternate_email: str = None,
142
- mobile: str = None,
143
- site_names: list[str] = None,
144
- role_names: list[str] = None,
145
- is_active: bool = None,
146
- is_staff: bool = None,
147
- resource_name: str = None,
137
+ username: str | None = None,
138
+ first_name: str | None = None,
139
+ last_name: str | None = None,
140
+ job_title: str | None = None,
141
+ email: str | None = None,
142
+ alternate_email: str | None = None,
143
+ mobile: str | None = None,
144
+ site_names: list[str] | None = None,
145
+ role_names: list[str] | None = None,
146
+ is_active: bool | None = None,
147
+ is_staff: bool | None = None,
148
+ resource_name: str | None = None,
148
149
  created_email_template: Template | None = None,
149
150
  updated_email_template: Template | None = None,
150
151
  send_email_to_user: Any | None = None,
@@ -200,7 +201,7 @@ class UserImporter:
200
201
  try:
201
202
  self.email_message.send(fail_silently=False)
202
203
  except ConnectionRefusedError:
203
- print(self.email_message.body)
204
+ sys.stdout.write(f"{self.email_message.body}\n")
204
205
 
205
206
  def validate_username(self) -> None:
206
207
  if not self.username:
@@ -241,12 +242,12 @@ class UserImporter:
241
242
  for site_name in site_names:
242
243
  try:
243
244
  site = Site.objects.get(name=site_name)
244
- except ObjectDoesNotExist:
245
+ except ObjectDoesNotExist as e:
245
246
  sites = [s.name for s in Site.objects.all()]
246
247
  raise UserImporterError(
247
248
  f"Unknown site for user. Expected one of {sites}. "
248
249
  f"Got {self.user.username}, {site_name}."
249
- )
250
+ ) from e
250
251
  else:
251
252
  self.user.userprofile.sites.add(site)
252
253
 
@@ -256,11 +257,11 @@ class UserImporter:
256
257
  for role_name in role_names:
257
258
  try:
258
259
  role = Role.objects.get(name__iexact=role_name)
259
- except ObjectDoesNotExist:
260
+ except ObjectDoesNotExist as e:
260
261
  raise UserImporterError(
261
262
  f"Unknown role for user. Got role `{role_name}` "
262
263
  f"for user `{self.user.username}`"
263
- )
264
+ ) from e
264
265
  else:
265
266
  self.user.userprofile.roles.add(role)
266
267
 
@@ -25,5 +25,5 @@ class Command(BaseCommand):
25
25
  help="Export new users to file",
26
26
  )
27
27
 
28
- def handle(self, *args, **options):
28
+ def handle(self, *args, **options): # noqa: ARG002
29
29
  export_users(options["csvfile"])
@@ -4,6 +4,6 @@ from edc_auth.fix_export_permissions import ExportPermissionsFixer
4
4
 
5
5
 
6
6
  class Command(BaseCommand):
7
- def handle(self, *args, **options):
7
+ def handle(self, *args, **options): # noqa: ARG002
8
8
  fixer = ExportPermissionsFixer()
9
9
  fixer.fix()
@@ -65,7 +65,7 @@ class Command(BaseCommand):
65
65
  help="Limit import to a single username",
66
66
  )
67
67
 
68
- def handle(self, *args, **options):
68
+ def handle(self, *args, **options): # noqa: ARG002
69
69
  import_users(
70
70
  options["csvfile"],
71
71
  resource_name=options["resource_name"],
@@ -25,11 +25,11 @@ class Command(BaseCommand):
25
25
  "--email", action="store_true", dest="email", help="Alternate email"
26
26
  )
27
27
 
28
- def handle(self, *args, **options):
28
+ def handle(self, *args, **options): # noqa: ARG002
29
29
  try:
30
30
  user = User.objects.get(username=options["username"])
31
31
  except ObjectDoesNotExist as e:
32
- raise CommandError(e)
32
+ raise CommandError(e) from e
33
33
  else:
34
34
  p = PasswordSetter(super_username=options["super_user"])
35
35
  p.reset_user(username=options["username"])
@@ -10,7 +10,7 @@ from .user_profile import UserProfile
10
10
  def update_user_profile_on_post_save(sender, instance, raw, **kwargs):
11
11
  if not raw:
12
12
  try:
13
- instance.userprofile
13
+ instance.userprofile # noqa: B018
14
14
  except ObjectDoesNotExist:
15
15
  UserProfile.objects.create(user=instance)
16
16
 
@@ -4,7 +4,6 @@ from django.core.validators import RegexValidator
4
4
  from django.db import models
5
5
  from django.db.models.deletion import CASCADE
6
6
  from django.utils.html import format_html
7
- from django.utils.safestring import mark_safe
8
7
  from django.utils.translation import gettext_lazy as _
9
8
 
10
9
  from edc_export.choices import EXPORT_FORMATS
@@ -50,7 +49,7 @@ class UserProfile(NotificationUserProfileModelMixin, models.Model):
50
49
  blank=True,
51
50
  help_text=format_html(
52
51
  'Change in <a href="{href}">{label}</a>',
53
- href=mark_safe("/edc_label/"), # nosec B703, B308
52
+ href="/edc_label/",
54
53
  label="Edc Label Administration",
55
54
  ),
56
55
  )
@@ -61,7 +60,7 @@ class UserProfile(NotificationUserProfileModelMixin, models.Model):
61
60
  blank=True,
62
61
  help_text=format_html(
63
62
  'Change in <a href="{href}">{label}</a>',
64
- href=mark_safe("/edc_label/"), # nosec B703, B308
63
+ href="/edc_label/",
65
64
  label="Edc Label Administration",
66
65
  ),
67
66
  )
@@ -72,7 +71,7 @@ class UserProfile(NotificationUserProfileModelMixin, models.Model):
72
71
  blank=True,
73
72
  help_text=format_html(
74
73
  'Change in <a href="{href}">{label}</a>',
75
- href=mark_safe("/edc_label/"), # nosec B703, B308
74
+ href="/edc_label/",
76
75
  label="Edc Label Administration",
77
76
  ),
78
77
  )
@@ -91,7 +90,7 @@ class UserProfile(NotificationUserProfileModelMixin, models.Model):
91
90
  def __str__(self):
92
91
  return self.user.username
93
92
 
94
- def add_groups_for_roles(self, pk_set):
93
+ def add_groups_for_roles(self, pk_set): # noqa: ARG002
95
94
  """Add groups to this user for the selected roles.
96
95
 
97
96
  Called by m2m signal.
@@ -37,17 +37,17 @@ class PasswordSetter:
37
37
  def get_administrator_fullname(super_username: str) -> str:
38
38
  try:
39
39
  obj = User.objects.get(username=super_username)
40
- except ObjectDoesNotExist:
40
+ except ObjectDoesNotExist as e:
41
41
  raise PasswordSetterError(
42
42
  "Need the username of the administrator / super user. Got None."
43
- )
43
+ ) from e
44
44
  return f"{obj.first_name} {obj.last_name}"
45
45
 
46
46
  def reset_all(self) -> None:
47
47
  users = User.objects.filter(is_active=True, is_staff=True, is_superuser=False)
48
48
  self._reset(users)
49
49
 
50
- def reset_by_groups(self, group_names: list[str] = None) -> None:
50
+ def reset_by_groups(self, group_names: list[str]) -> None:
51
51
  users = User.objects.filter(
52
52
  groups__name__in=group_names,
53
53
  is_active=True,
@@ -64,7 +64,7 @@ class PasswordSetter:
64
64
  usernames = [username]
65
65
  self.reset_users(usernames)
66
66
 
67
- def reset_by_sites(self, site_names: list[str] = None) -> None:
67
+ def reset_by_sites(self, site_names: list[str]) -> None:
68
68
  users = User.objects.filter(
69
69
  userprofile__sites__name__in=site_names,
70
70
  is_active=True,
@@ -9,8 +9,8 @@ style = color_style()
9
9
  def post_migrate_user_groups_and_roles(sender=None, **kwargs):
10
10
  """Update Groups, Role model with EDC defaults."""
11
11
 
12
- from .auth_updater import AuthUpdater
13
- from .auth_updater.group_updater import CodenameDoesNotExist
12
+ from .auth_updater import AuthUpdater # noqa: PLC0415
13
+ from .auth_updater.group_updater import CodenameDoesNotExist # noqa: PLC0415
14
14
 
15
15
  try:
16
16
  AuthUpdater(apps=django_apps, verbose=True)
@@ -18,7 +18,7 @@ def change_password(user, nwords: int | None = None) -> str:
18
18
  return password
19
19
 
20
20
 
21
- def send_new_credentials_to_user(user, nwords: int | None = None) -> EmailMessage:
21
+ def send_new_credentials_to_user(user, nwords: int | None = None) -> int:
22
22
  body = change_user_template
23
23
  site_names = "\n - ".join([s.name for s in user.userprofile.sites.all()])
24
24
  role_names = "\n - ".join([r.display_name for r in user.userprofile.roles.all()])
edc_auth/system_checks.py CHANGED
@@ -1,7 +1,8 @@
1
1
  import os
2
+ from pathlib import Path
2
3
 
3
4
  from django.conf import settings
4
- from django.core.checks import CheckMessage, Warning
5
+ from django.core.checks import CheckMessage, Warning # noqa: A004
5
6
  from django.core.management import color_style
6
7
 
7
8
  style = color_style()
@@ -10,7 +11,7 @@ style = color_style()
10
11
  def check_etc_dir(app_configs, **kwargs) -> list[CheckMessage]:
11
12
  errors = []
12
13
  try:
13
- settings.ETC_DIR
14
+ settings.ETC_DIR # noqa: B018
14
15
  except AttributeError:
15
16
  pass
16
17
  else:
@@ -37,11 +38,11 @@ def check_etc_dir(app_configs, **kwargs) -> list[CheckMessage]:
37
38
  def check_static_root(app_configs, **kwargs) -> list[CheckMessage]:
38
39
  errors = []
39
40
  try:
40
- settings.STATIC_ROOT
41
+ settings.STATIC_ROOT # noqa: B018
41
42
  except AttributeError:
42
43
  pass
43
44
  else:
44
- if settings.STATIC_ROOT and not os.path.exists(settings.STATIC_ROOT):
45
+ if settings.STATIC_ROOT and not Path(settings.STATIC_ROOT).exists():
45
46
  errors.append(
46
47
  Warning(
47
48
  f"Folder does not exist. Got {settings.STATIC_ROOT}",
@@ -54,7 +55,7 @@ def check_static_root(app_configs, **kwargs) -> list[CheckMessage]:
54
55
  def check_auth_updater(app_configs, **kwargs) -> list[CheckMessage]:
55
56
  errors = []
56
57
  try:
57
- settings.EDC_AUTH_SKIP_AUTH_UPDATER
58
+ settings.EDC_AUTH_SKIP_AUTH_UPDATER # noqa: B018
58
59
  except AttributeError:
59
60
  pass
60
61
  else:
@@ -72,7 +73,7 @@ def check_auth_updater(app_configs, **kwargs) -> list[CheckMessage]:
72
73
  def check_site_auths(app_configs, **kwargs) -> list[CheckMessage]:
73
74
  errors = []
74
75
  try:
75
- settings.EDC_AUTH_SKIP_AUTH_UPDATER
76
+ settings.EDC_AUTH_SKIP_AUTH_UPDATER # noqa: B018
76
77
  except AttributeError:
77
78
  pass
78
79
  else: