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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clinicedc
3
- Version: 2.0.16
3
+ Version: 2.0.18
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
@@ -1963,11 +1963,11 @@ edc_model_form/mixins/inline_model_form_mixin.py,sha256=dxpzFcwHoNi2y7vWF1QdAqOb
1963
1963
  edc_model_form/mixins/report_datetime_modelform_mixin.py,sha256=f1DrM-aUh2o3DM65MM3nwiZUXhhnvth8_3tvbS1cWOQ,1008
1964
1964
  edc_model_form/urls.py,sha256=_sVCnQeiAFRYKhxga3_DjoKj_4bgs1s2gjcynDiapvA,111
1965
1965
  edc_model_form/utils.py,sha256=gGe3etrp5YF4AKMGFIR3I9V1CfX4c5Wm6fK-8JkUeT4,538
1966
- edc_model_to_dataframe/__init__.py,sha256=iDR_F5oKkKDL9FfBXl0WKpwc2iOWbOlY-8wpCipBNnQ,115
1966
+ edc_model_to_dataframe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1967
1967
  edc_model_to_dataframe/apps.py,sha256=US1ehhJPgkvmIDZXiUPMoSjHTWIztUbYGtx_azTXPIQ,290
1968
1968
  edc_model_to_dataframe/constants.py,sha256=xgCr2ZXUsjZqf4wfpY0JBhQoARzQEVS8tnkfBWwOMVQ,702
1969
- edc_model_to_dataframe/model_to_dataframe.py,sha256=DDuDIEpgEHjTTrqcjdYMLERvFl9h-HHhxYaapFepO9U,18829
1970
- edc_model_to_dataframe/read_frame_edc.py,sha256=D3Bai4ce4u6942OU8sad1OEAeDRIT1DQxYOQib5AMDE,791
1969
+ edc_model_to_dataframe/model_to_dataframe.py,sha256=cOTcoe9ivJERAXt3dULtoon6j9_cgh2-T-y3P0FBimo,18493
1970
+ edc_model_to_dataframe/read_frame_edc.py,sha256=UNe2f5bJi1Wkn4Jyva5TMnhyxk8vvGpG4U12kGyqqVY,820
1971
1971
  edc_model_to_dataframe/urls.py,sha256=KChLHeE6yfONC6IdMm3Q4U3u7tmy_Mb1w2lrbpFz96g,148
1972
1972
  edc_navbar/__init__.py,sha256=Y95juevvOawGZmOV3Ofef7oGwYSWWttAYT0v0mehkJc,195
1973
1973
  edc_navbar/apps.py,sha256=fiWHsCYaDnHXNfYUu6DuvlAcO2k45-zkdbuXwXI3ksc,367
@@ -2133,7 +2133,7 @@ edc_pdutils/constants.py,sha256=v4J4xjBJC49IeLQqVrjZyqF1OKAzOjm-TMqF38siR6g,785
2133
2133
  edc_pdutils/database.py,sha256=bevHPm0BDsMai6tfR94nERV3bIOQz4pkoniGYp0Ha3s,4468
2134
2134
  edc_pdutils/dataframes/__init__.py,sha256=mr2vvMm1E5sj5VXbk3iUKlZy2HeS3odZlQyi5HhiiEU,264
2135
2135
  edc_pdutils/dataframes/get_appointments.py,sha256=R3lzLbloR-pabMXREhcgmrfMC1CP6d6DrnxNyLbTOQI,2503
2136
- edc_pdutils/dataframes/get_crf.py,sha256=3y9R6squz1eza0OWiAdaNVEIdBO_2QhB1-9br97NC_s,4453
2136
+ edc_pdutils/dataframes/get_crf.py,sha256=WVRs9VHTpaYBRAXvbWeoDGNGPqe096vUp0hegZPEFyc,4468
2137
2137
  edc_pdutils/dataframes/get_eos.py,sha256=qzlERHSm-vydI8M4XuSF5oIIcBtYbu7PxKXWXb5wikQ,1350
2138
2138
  edc_pdutils/dataframes/get_next_appointments.py,sha256=VUuTQ5T15PxAVNlJId2rH70PyAzaHXqFGWJH0qd4Kfs,784
2139
2139
  edc_pdutils/dataframes/get_subject_consent.py,sha256=e-G4rCdRtv2c9dBDA6HsezoZgxj8DPtyktnc5b6Mvj0,2030
@@ -2142,7 +2142,7 @@ edc_pdutils/df_exporters/__init__.py,sha256=K2CbrO9yrBEr_9k6nRbSOepBhBWY1tCcHCd_
2142
2142
  edc_pdutils/df_exporters/csv_crf_inline_tables_exporter.py,sha256=OUV6BGVFgYXQ3osccPVqAZ_2hRbfQew86BLqFkuEFS8,3218
2143
2143
  edc_pdutils/df_exporters/csv_crf_tables_exporter.py,sha256=hBx5n-Khr9ooO_RfTtEUjyDx6JL0QuNCmFpFDI7azXY,1047
2144
2144
  edc_pdutils/df_exporters/csv_exporter.py,sha256=1JE9DGWKIfA1iTXywz9gVytW1aP7Ebfj3k7Mt5qvw2k,10029
2145
- edc_pdutils/df_exporters/csv_model_exporter.py,sha256=rUaAuSHugLZQEFmVSzoIUjszeFYeTxUZAZWUsawxon0,1567
2145
+ edc_pdutils/df_exporters/csv_model_exporter.py,sha256=7HJvtsgIuC5EgGyEc_YLE3cEHim-I-Na4UKZy0_9sZw,1586
2146
2146
  edc_pdutils/df_exporters/csv_noncrf_tables_exporter.py,sha256=twgj1hM53KgiqbHoV1m54eEuZ6-I6BWdJcwNLmoefiY,788
2147
2147
  edc_pdutils/df_exporters/tables_exporter.py,sha256=4juRZ87xl7Ph6NzC-iss2pcyq1muLmhezgz6IpkYP7g,4576
2148
2148
  edc_pdutils/df_handlers/__init__.py,sha256=8c3N4G_fmc_6bshSjAtEu-aQelGzN4ZeXU7J6s0lfRo,123
@@ -2157,7 +2157,7 @@ edc_pdutils/dialects/rs_dialect.py,sha256=G1aGOeefsJj5f0souyoJBBQ-AXHyli0Gxqeib6
2157
2157
  edc_pdutils/helper.py,sha256=dRujtvFA1pbuPoFjJ5M2ElAdA1j5qMbfGMspg1weD5k,1667
2158
2158
  edc_pdutils/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2159
2159
  edc_pdutils/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2160
- edc_pdutils/management/commands/export_models.py,sha256=hLatz0dSvRAzlTe_qNwIElYwOuWiwJd8lAZpjDsBNQw,9554
2160
+ edc_pdutils/management/commands/export_models.py,sha256=ALBuoBv0rSmXw8FSIabkkZer7Y_rQvXqVYUmnQS704s,9573
2161
2161
  edc_pdutils/mappings.py,sha256=qlUrcoQdHg5vCEizEwF6EByqJedmYDVT6r94QDEi-Hg,77
2162
2162
  edc_pdutils/migrations/0001_initial.py,sha256=yZ8Ap-c1W87E-Bud74X8BAcbqgjWKQsOl3WykJRz3Xw,12271
2163
2163
  edc_pdutils/migrations/0002_auto_20180921_2242.py,sha256=J2gDXyF7AnHZiZUTDp4CsnGl87QGdu4t8vTW34Ww4Bs,548
@@ -2186,7 +2186,7 @@ edc_pdutils/utils/datetime_to_date.py,sha256=VQd6BVHxB6c0l5LT19j0-R5so3gVtEB_xFC
2186
2186
  edc_pdutils/utils/decrypt.py,sha256=zZhcnOkpgngoO_YEJZHFllFlLLnt8w2fRsqDFMirI9g,652
2187
2187
  edc_pdutils/utils/get_export_folder.py,sha256=l95sw3PGf2Sw_tFWNAkRvcZf5PDwUhqiCHeXBbCnvUU,260
2188
2188
  edc_pdutils/utils/identity256.py,sha256=3o5nAx8bKPPfi3zuFVsdYMP2VMygIKUJ7_7L6-i3wPo,717
2189
- edc_pdutils/utils/missing_subject_identifiers.py,sha256=UGWdg9Mr1xvsEgq0jUx7sX3oK26fN1zDfTNCYw1-lZI,1811
2189
+ edc_pdutils/utils/missing_subject_identifiers.py,sha256=fzEa-U76st6EB7c2bf3YqQpIL3FuLvOpn_Ht-DP3hoE,1830
2190
2190
  edc_pdutils/utils/model_from_table_name.py,sha256=ahR04BOxoKxOPMob58fSH7gj3CNbrRMK_j8bC1xggUE,167
2191
2191
  edc_pdutils/utils/refresh_model_from_dataframe.py,sha256=Ct6sYEt7zOMm0jC23StpzLSbaStbzLP8SX3dTIOryZE,543
2192
2192
  edc_pdutils/utils/table_names.py,sha256=T8gXHN5ALXxshRP23nC3unzwIamLQRi7iQezBZvn1eA,1869
@@ -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.16.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
3410
- clinicedc-2.0.16.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
3411
- clinicedc-2.0.16.dist-info/METADATA,sha256=yACQMEfCdkmBMoz9yz7R4jaTs-ToDfcahB4QqGBUqII,15899
3412
- clinicedc-2.0.16.dist-info/RECORD,,
3409
+ clinicedc-2.0.18.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
3410
+ clinicedc-2.0.18.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
3411
+ clinicedc-2.0.18.dist-info/METADATA,sha256=7nXGZliVuraX2Qnysh6GdRt_PFSZ3A-6bFDx6AyR538,15899
3412
+ clinicedc-2.0.18.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- from .model_to_dataframe import ModelToDataframe, ModelToDataframeError
2
- from .read_frame_edc import read_frame_edc
@@ -1,28 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  from copy import copy
4
- from typing import TYPE_CHECKING
5
5
 
6
6
  import numpy as np
7
7
  import pandas as pd
8
8
  from django.apps import apps as django_apps
9
+ from django.contrib.sites.models import Site
9
10
  from django.core.exceptions import FieldError
10
11
  from django.db import OperationalError
12
+ from django.db.models import QuerySet
11
13
  from django_crypto_fields.utils import get_encrypted_fields, has_encrypted_fields
12
14
  from django_pandas.io import read_frame
15
+ from pandas import Series
13
16
 
14
- from .constants import ACTION_ITEM_COLUMNS, SYSTEM_COLUMNS
15
-
16
- if TYPE_CHECKING:
17
- from django.db.models import QuerySet
18
-
19
- from edc_model.models import BaseUuidModel
20
- from edc_sites.model_mixins import SiteModelMixin
21
-
22
- class MyModel(SiteModelMixin, BaseUuidModel):
23
- class Meta(BaseUuidModel.Meta):
24
- pass
17
+ from edc_lab.models import Panel
18
+ from edc_list_data.model_mixins import ListModelMixin, ListUuidModelMixin
25
19
 
20
+ from .constants import ACTION_ITEM_COLUMNS, SYSTEM_COLUMNS
26
21
 
27
22
  __all__ = ["ModelToDataframe", "ModelToDataframeError"]
28
23
 
@@ -52,16 +47,16 @@ class ModelToDataframe:
52
47
  See also: get_crf()
53
48
  """
54
49
 
55
- sys_field_names: list[str] = [
50
+ sys_field_names: tuple[str, ...] = (
56
51
  "_state",
57
52
  "_user_container_instance",
58
53
  "_domain_cache",
59
54
  "using",
60
55
  "slug",
61
- ]
62
- edc_sys_columns: list[str] = SYSTEM_COLUMNS
63
- action_item_columns: list[str] = ACTION_ITEM_COLUMNS
64
- illegal_chars: dict[str] = {
56
+ )
57
+ edc_sys_columns: tuple[str, ...] = SYSTEM_COLUMNS
58
+ action_item_columns: tuple[str, ...] = ACTION_ITEM_COLUMNS
59
+ illegal_chars: dict[str, str] = { # noqa: RUF012
65
60
  "\u2019": "'",
66
61
  "\u2018": "'",
67
62
  "\u201d": '"',
@@ -72,7 +67,7 @@ class ModelToDataframe:
72
67
  def __init__(
73
68
  self,
74
69
  model: str | None = None,
75
- queryset: QuerySet | None = None,
70
+ queryset: [QuerySet] | None = None,
76
71
  query_filter: dict | None = None,
77
72
  decrypt: bool | None = None,
78
73
  drop_sys_columns: bool | None = None,
@@ -104,7 +99,7 @@ class ModelToDataframe:
104
99
  try:
105
100
  self.model_cls = django_apps.get_model(self.model)
106
101
  except LookupError as e:
107
- raise LookupError(f"Model is {self.model}. Got `{e}`")
102
+ raise LookupError(f"Model is {self.model}. Got `{e}`") from e
108
103
  if self.sites:
109
104
  try:
110
105
  if queryset:
@@ -151,7 +146,7 @@ class ModelToDataframe:
151
146
 
152
147
  dataframe = self.merge_m2ms(dataframe)
153
148
 
154
- dataframe.rename(columns=self.columns, inplace=True)
149
+ dataframe = dataframe.rename(columns=self.columns)
155
150
 
156
151
  # remove timezone if asked
157
152
  if self.remove_timezone:
@@ -174,12 +169,12 @@ class ModelToDataframe:
174
169
  dataframe[column] = dataframe[column].dt.total_seconds()
175
170
 
176
171
  # fillna
177
- dataframe.fillna(value=np.nan, axis=0, inplace=True)
172
+ dataframe = dataframe.fillna(value=np.nan, axis=0)
178
173
 
179
174
  # remove illegal chars
180
175
  for column in list(dataframe.select_dtypes(include=["object"]).columns):
181
176
  dataframe[column] = dataframe.apply(
182
- lambda x: self._clean_chars(x[column]), axis=1
177
+ lambda x, col=column: self._clean_chars(x[col]), axis=1
183
178
  )
184
179
  self._dataframe = dataframe
185
180
  return self._dataframe
@@ -188,7 +183,7 @@ class ModelToDataframe:
188
183
  queryset = self.queryset.values_list(*self.columns).filter(**self.query_filter)
189
184
  return pd.DataFrame(list(queryset), columns=[v for v in self.columns])
190
185
 
191
- def get_dataframe_with_encrypted_fields(self, row_count: int) -> pd.DataFrame:
186
+ def get_dataframe_with_encrypted_fields(self, row_count: int) -> pd.DataFrame: # noqa: ARG002
192
187
  df = read_frame(
193
188
  self.queryset.filter(**self.query_filter), verbose=self.read_frame_verbose
194
189
  )
@@ -233,28 +228,27 @@ class ModelToDataframe:
233
228
  dataframe = dataframe.merge(df_m2m, on="id", how="left")
234
229
  return dataframe
235
230
 
236
- def _clean_chars(self, s):
237
- try:
238
- s = s if s else s
239
- except ValueError:
240
- pass
241
- else:
242
- if s:
243
- for k, v in self.illegal_chars.items():
244
- try:
245
- s = s.replace(k, v)
246
- except (AttributeError, TypeError):
247
- break
248
- return s
231
+ def _clean_chars(self, s: Series) -> Series:
232
+ if not s.empty:
233
+ for k, v in self.illegal_chars.items():
234
+ try:
235
+ s = s.replace(k, v)
236
+ except (AttributeError, TypeError):
237
+ break
238
+ return s
239
+ return np.nan
249
240
 
250
241
  def move_sys_columns_to_end(self, columns: dict[str, str]) -> dict[str, str]:
251
242
  system_columns = [
252
243
  f.name for f in self.model_cls._meta.get_fields() if f.name in SYSTEM_COLUMNS
253
244
  ]
254
245
  new_columns = {k: v for k, v in columns.items() if k not in system_columns}
255
- if system_columns:
256
- if len(new_columns.keys()) != len(columns.keys()) and not self.drop_sys_columns:
257
- new_columns.update({k: k for k in system_columns})
246
+ if (
247
+ system_columns
248
+ and len(new_columns.keys()) != len(columns.keys())
249
+ and not self.drop_sys_columns
250
+ ):
251
+ new_columns.update({k: k for k in system_columns})
258
252
  return new_columns
259
253
 
260
254
  def move_action_item_columns(self, columns: dict[str, str]) -> dict[str, str]:
@@ -262,12 +256,11 @@ class ModelToDataframe:
262
256
  f.name for f in self.model_cls._meta.get_fields() if f.name in ACTION_ITEM_COLUMNS
263
257
  ]
264
258
  new_columns = {k: v for k, v in columns.items() if k not in ACTION_ITEM_COLUMNS}
265
- if action_item_columns:
266
- if (
267
- len(new_columns.keys()) != len(columns.keys())
268
- and not self.drop_action_item_columns
269
- ):
270
- new_columns.update({k: k for k in ACTION_ITEM_COLUMNS})
259
+ if action_item_columns and (
260
+ len(new_columns.keys()) != len(columns.keys())
261
+ and not self.drop_action_item_columns
262
+ ):
263
+ new_columns.update({k: k for k in ACTION_ITEM_COLUMNS})
271
264
  return new_columns
272
265
 
273
266
  @property
@@ -285,12 +278,10 @@ class ModelToDataframe:
285
278
  columns = {col: col for col in columns_list}
286
279
  for column_name in columns_list:
287
280
  if column_name.endswith("_visit_id"):
288
- try:
281
+ with contextlib.suppress(FieldError):
289
282
  columns = self.add_columns_for_subject_visit(
290
283
  column_name=column_name, columns=columns
291
284
  )
292
- except FieldError:
293
- pass
294
285
  if column_name.endswith("_requisition") or column_name.endswith(
295
286
  "requisition_id"
296
287
  ):
@@ -316,10 +307,8 @@ class ModelToDataframe:
316
307
  else:
317
308
  raise
318
309
  for name in self.sys_field_names:
319
- try:
310
+ with contextlib.suppress(ValueError):
320
311
  columns_list.remove(name)
321
- except ValueError:
322
- pass
323
312
  if not self.decrypt:
324
313
  columns_list = [col for col in columns_list if col not in self.encrypted_columns]
325
314
  return columns_list
@@ -338,7 +327,6 @@ class ModelToDataframe:
338
327
  @property
339
328
  def list_columns(self) -> list[str]:
340
329
  """Return a list of column names with fk to a list model."""
341
- from edc_list_data.model_mixins import ListModelMixin, ListUuidModelMixin
342
330
 
343
331
  if not self._list_columns:
344
332
  list_columns = []
@@ -348,14 +336,13 @@ class ModelToDataframe:
348
336
  and fld_cls.related_model
349
337
  and issubclass(fld_cls.related_model, (ListModelMixin, ListUuidModelMixin))
350
338
  ):
351
- list_columns.append(fld_cls.attname)
339
+ list_columns.append(fld_cls.attname) # noqa: PERF401
352
340
  self._list_columns = list(set(list_columns))
353
341
  return self._list_columns
354
342
 
355
343
  @property
356
344
  def site_columns(self) -> list[str]:
357
345
  """Return a list of column names with fk to a site model."""
358
- from django.contrib.sites.models import Site
359
346
 
360
347
  if not self._site_columns:
361
348
  site_columns = []
@@ -372,10 +359,6 @@ class ModelToDataframe:
372
359
  @property
373
360
  def other_columns(self) -> list[str]:
374
361
  """Return other column names with fk to a common models."""
375
- from django.contrib.sites.models import Site
376
-
377
- from edc_lab.models import Panel
378
-
379
362
  related_model = [Site, Panel]
380
363
  if not self._list_columns:
381
364
  list_columns = []
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.apps import apps as django_apps
2
4
  from django.db.models import QuerySet
3
5
 
@@ -7,7 +9,7 @@ __all__ = ["read_frame_edc"]
7
9
 
8
10
 
9
11
  def read_frame_edc(
10
- queryset: QuerySet | str = None,
12
+ queryset: QuerySet | str,
11
13
  drop_sys_columns: bool | None = None,
12
14
  drop_action_item_columns: bool | None = None,
13
15
  read_frame_verbose: bool | None = None,
@@ -6,7 +6,7 @@ from django.contrib.sites.models import Site
6
6
  from django.db import models
7
7
  from django_pandas.io import read_frame
8
8
 
9
- from edc_model_to_dataframe import read_frame_edc
9
+ from edc_model_to_dataframe.read_frame_edc import read_frame_edc
10
10
  from edc_registration.models import RegisteredSubject
11
11
 
12
12
  from ..constants import SYSTEM_COLUMNS
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from django.core.management.color import color_style
7
7
 
8
- from edc_model_to_dataframe import ModelToDataframe
8
+ from edc_model_to_dataframe.model_to_dataframe import ModelToDataframe
9
9
 
10
10
  from .csv_exporter import CsvExporter
11
11
 
@@ -10,7 +10,7 @@ from django.core.exceptions import ObjectDoesNotExist
10
10
  from django.core.management import CommandError, color_style
11
11
  from django.core.management.base import BaseCommand
12
12
 
13
- from edc_model_to_dataframe import ModelToDataframe
13
+ from edc_model_to_dataframe.model_to_dataframe import ModelToDataframe
14
14
  from edc_pdutils.df_exporters import Exporter
15
15
  from edc_pdutils.utils import get_model_names
16
16
  from edc_sites.site import sites
@@ -3,7 +3,7 @@ from warnings import warn
3
3
  import pandas as pd
4
4
  from django.apps import apps as django_apps
5
5
 
6
- from edc_model_to_dataframe import ModelToDataframe
6
+ from edc_model_to_dataframe.model_to_dataframe import ModelToDataframe
7
7
 
8
8
 
9
9
  def missing_subject_identifiers(
@@ -42,7 +42,7 @@ def missing_subject_identifiers(
42
42
 
43
43
  if len(df_missing.index) > 0 and verbose:
44
44
  warn(
45
- f'There are {len(df_missing["identifier"])} subject identifiers '
45
+ f"There are {len(df_missing['identifier'])} subject identifiers "
46
46
  f"missing from {model}."
47
47
  )
48
48
  return df_missing["identifier"]