clinicedc 2.0.23__py3-none-any.whl → 2.0.24__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.
- {clinicedc-2.0.23.dist-info → clinicedc-2.0.24.dist-info}/METADATA +1 -1
- {clinicedc-2.0.23.dist-info → clinicedc-2.0.24.dist-info}/RECORD +7 -7
- edc_randomization/randomization_list_importer.py +4 -4
- edc_randomization/randomization_list_verifier.py +29 -24
- edc_randomization/site_randomizers.py +25 -8
- {clinicedc-2.0.23.dist-info → clinicedc-2.0.24.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.23.dist-info → clinicedc-2.0.24.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clinicedc
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.24
|
|
4
4
|
Summary: A clinical trials data management framework built on Django
|
|
5
5
|
Keywords: django,clinicedc,edc,clinical trials,research,data management,esource
|
|
6
6
|
Author: Erik van Widenfelt, Jonathan Willitts
|
|
@@ -2793,11 +2793,11 @@ edc_randomization/model_mixins.py,sha256=pKLkZJeYgobKPyHVJTby8Q7zBKQoflbLgraTN4p
|
|
|
2793
2793
|
edc_randomization/models/__init__.py,sha256=iaJ6FM7VVqLpp8M-OjVWjohp4ELdxtPXqbEiT3iN5Tw,94
|
|
2794
2794
|
edc_randomization/models/edc_permissions.py,sha256=f6P4zXxLQdTAbn2KnFlwfE86Lmzj7Ecp4JJ2F8mrwTc,286
|
|
2795
2795
|
edc_randomization/models/randomization_list.py,sha256=Hd5yUSZ5HBKhNzYdlbJufab8U2x3Dzw8n4WXnYzJxyc,253
|
|
2796
|
-
edc_randomization/randomization_list_importer.py,sha256=
|
|
2797
|
-
edc_randomization/randomization_list_verifier.py,sha256=
|
|
2796
|
+
edc_randomization/randomization_list_importer.py,sha256=9jIJTG7rGjze4WmaFsJaw4qhFvy5mugZ4mx1CKKV6_o,12416
|
|
2797
|
+
edc_randomization/randomization_list_verifier.py,sha256=b9-ZbaWSSv6fCrrDgHjijUACTMsUuU_htbkHqAcE8l4,6669
|
|
2798
2798
|
edc_randomization/randomizer.py,sha256=N57PvCGjsjlw4r4V-zE5K7uWnLUw4QwZREu-mQ-O_4U,12939
|
|
2799
2799
|
edc_randomization/randomizers.py,sha256=JvMDAnsgvRZkl50Bawm2iLsyw3bfWfGwBafn54K5g44,297
|
|
2800
|
-
edc_randomization/site_randomizers.py,sha256=
|
|
2800
|
+
edc_randomization/site_randomizers.py,sha256=et5Yf92ld8qgn-AThrBTRALB3WInI03UK4yGw2PlsKo,4499
|
|
2801
2801
|
edc_randomization/system_checks.py,sha256=S_2Vkq3J3DQVEXOV3JNNlCzuZcl1l34-tTnaBaSZaBk,3025
|
|
2802
2802
|
edc_randomization/urls.py,sha256=yQnOoy5U5uL00f7_JJcZk7toskmZunG_kJdl-epCV9U,223
|
|
2803
2803
|
edc_randomization/utils.py,sha256=uRTtoyAuWo5D6y65ZHBWMSody8IMJBK6cS3mFmJGIMw,5730
|
|
@@ -3406,7 +3406,7 @@ edc_vitals/models/fields/waist_circumference.py,sha256=fZcHFDdEwWLjIVLktKrFCD9UU
|
|
|
3406
3406
|
edc_vitals/models/fields/weight.py,sha256=zo9_9e3Cpu0UqoRbWS-iDkcDo6fK80b1dDQy4x4MyxE,921
|
|
3407
3407
|
edc_vitals/utils.py,sha256=vXid44KUXxeaSyund_y5MNXc5DFJs052_PwUAjszE2k,1384
|
|
3408
3408
|
edc_vitals/validators.py,sha256=vNiElWMs0rRnHRNuVoPLRf0rW_C_0xcfUyep1Y_Si5s,156
|
|
3409
|
-
clinicedc-2.0.
|
|
3410
|
-
clinicedc-2.0.
|
|
3411
|
-
clinicedc-2.0.
|
|
3412
|
-
clinicedc-2.0.
|
|
3409
|
+
clinicedc-2.0.24.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
3410
|
+
clinicedc-2.0.24.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
|
|
3411
|
+
clinicedc-2.0.24.dist-info/METADATA,sha256=SanRpzDjK5JhHNRsmoNLCYZtF9Q9k3bXXX2CdYsZ7ME,15787
|
|
3412
|
+
clinicedc-2.0.24.dist-info/RECORD,,
|
|
@@ -55,13 +55,13 @@ class RandomizationListImporter:
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
Format:
|
|
58
|
-
sid,assignment,
|
|
59
|
-
1,single_dose
|
|
60
|
-
2,two_doses
|
|
58
|
+
sid,site_name, assignment, description, orig_site, orig_allocation, orig_desc
|
|
59
|
+
1,gaborone,intervention,single_dose
|
|
60
|
+
2,gaborone,control,two_doses
|
|
61
61
|
...
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
|
-
required_csv_fieldnames =
|
|
64
|
+
required_csv_fieldnames = ("sid", "assignment", "site_name", "description")
|
|
65
65
|
verifier_cls = RandomizationListVerifier
|
|
66
66
|
|
|
67
67
|
def __init__(
|
|
@@ -31,7 +31,7 @@ class RandomizationListVerifier:
|
|
|
31
31
|
fieldnames=None,
|
|
32
32
|
sid_count_for_tests=None,
|
|
33
33
|
required_csv_fieldnames: list[str] | None = None,
|
|
34
|
-
**kwargs,
|
|
34
|
+
**kwargs, # noqa: ARG002
|
|
35
35
|
):
|
|
36
36
|
self.count: int = 0
|
|
37
37
|
self.messages: list[str] = []
|
|
@@ -68,33 +68,38 @@ class RandomizationListVerifier:
|
|
|
68
68
|
)
|
|
69
69
|
elif message := self.verify():
|
|
70
70
|
self.messages.append(message)
|
|
71
|
-
if self.messages
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
raise RandomizationListError(", ".join(self.messages))
|
|
71
|
+
if self.messages and (
|
|
72
|
+
"migrate" not in sys.argv
|
|
73
|
+
and "makemigrations" not in sys.argv
|
|
74
|
+
and "import_randomization_list" not in sys.argv
|
|
75
|
+
):
|
|
76
|
+
raise RandomizationListError(", ".join(self.messages))
|
|
78
77
|
|
|
79
78
|
def verify(self) -> str | None:
|
|
80
79
|
message = None
|
|
80
|
+
|
|
81
81
|
with self.randomizationlist_path.open(mode="r") as f:
|
|
82
82
|
reader = csv.DictReader(f)
|
|
83
|
-
for
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
83
|
+
all_rows = [{k: v.strip() for k, v in row.items() if k} for row in reader]
|
|
84
|
+
sorted_rows = sorted(
|
|
85
|
+
all_rows, key=lambda row: (row.get("site_name", ""), row.get("sid", ""))
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
for index, row in enumerate(sorted_rows, start=1):
|
|
89
|
+
sys.stdout.write(f"Index: {index}, SID: {row.get('sid')}, Row: {row}\n")
|
|
90
|
+
message = self.inspect_row(index - 1, row)
|
|
91
|
+
if message:
|
|
92
|
+
break
|
|
93
|
+
if self.sid_count_for_tests and index == self.sid_count_for_tests:
|
|
94
|
+
break
|
|
95
|
+
|
|
96
|
+
if not message and self.count != index:
|
|
97
|
+
message = (
|
|
98
|
+
f"Randomization list count is off. Expected {index} (CSV). "
|
|
99
|
+
f"Got {self.count} (model_cls). See file "
|
|
100
|
+
f"{self.randomizationlist_path}. "
|
|
101
|
+
f"Resolve this issue before using the system."
|
|
102
|
+
)
|
|
98
103
|
return message
|
|
99
104
|
|
|
100
105
|
def inspect_row(self, index: int, row) -> str | None:
|
|
@@ -103,7 +108,7 @@ class RandomizationListVerifier:
|
|
|
103
108
|
Note:Index is zero-based
|
|
104
109
|
"""
|
|
105
110
|
message = None
|
|
106
|
-
obj1 = self.randomizer_model_cls.objects.all().order_by("sid")[index]
|
|
111
|
+
obj1 = self.randomizer_model_cls.objects.all().order_by("site_name", "sid")[index]
|
|
107
112
|
try:
|
|
108
113
|
obj2 = self.randomizer_model_cls.objects.get(sid=row["sid"])
|
|
109
114
|
except ObjectDoesNotExist:
|
|
@@ -28,7 +28,22 @@ class SiteRandomizerError(Exception):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class SiteRandomizers:
|
|
31
|
-
"""Main controller of :class:`SiteRandomizers` objects.
|
|
31
|
+
"""Main controller of :class:`SiteRandomizers` objects.
|
|
32
|
+
|
|
33
|
+
To rescan the CSV file for randomizer additional slots:
|
|
34
|
+
|
|
35
|
+
from edc_randomization.site_randomizers import site_randomizers
|
|
36
|
+
# assuming the randimizer is "default"
|
|
37
|
+
site_randomizers.get("default").import_list(add=True,dryrun=True)
|
|
38
|
+
|
|
39
|
+
If all OK:
|
|
40
|
+
|
|
41
|
+
# assuming the randimizer is "default"
|
|
42
|
+
site_randomizers.get("default").import_list(add=True,dryrun=False)
|
|
43
|
+
|
|
44
|
+
See
|
|
45
|
+
|
|
46
|
+
"""
|
|
32
47
|
|
|
33
48
|
def __init__(self):
|
|
34
49
|
self._registry = {}
|
|
@@ -57,12 +72,12 @@ class SiteRandomizers:
|
|
|
57
72
|
def get(self, name):
|
|
58
73
|
try:
|
|
59
74
|
return self._registry[str(name)]
|
|
60
|
-
except KeyError:
|
|
75
|
+
except KeyError as e:
|
|
61
76
|
raise NotRegistered(
|
|
62
77
|
f"A Randomizer class by this name is not registered. "
|
|
63
78
|
f"Expected one of {list(self._registry.keys())}. "
|
|
64
79
|
f"Got '{name}'. See site_randomizer."
|
|
65
|
-
)
|
|
80
|
+
) from e
|
|
66
81
|
|
|
67
82
|
def get_by_model(self, model=None):
|
|
68
83
|
"""Returns the randomizer class for this model label_lower.
|
|
@@ -75,10 +90,12 @@ class SiteRandomizers:
|
|
|
75
90
|
return None
|
|
76
91
|
|
|
77
92
|
def get_as_choices(self):
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
93
|
+
return tuple(
|
|
94
|
+
[
|
|
95
|
+
(randomizer_cls.name, randomizer_cls.name)
|
|
96
|
+
for randomizer_cls in self._registry.values()
|
|
97
|
+
]
|
|
98
|
+
)
|
|
82
99
|
|
|
83
100
|
def randomize(
|
|
84
101
|
self,
|
|
@@ -115,7 +132,7 @@ class SiteRandomizers:
|
|
|
115
132
|
before_import_registry = copy.copy(site_randomizers._registry)
|
|
116
133
|
import_module(f"{app}.{module_name}")
|
|
117
134
|
if verbose:
|
|
118
|
-
sys.stdout.write(" * registered randomizer from
|
|
135
|
+
sys.stdout.write(f" * registered randomizer from '{app}'\n")
|
|
119
136
|
except Exception as e:
|
|
120
137
|
if f"No module named '{app}.{module_name}'" not in str(e):
|
|
121
138
|
raise
|
|
File without changes
|
|
File without changes
|