edc-vitals 1.0.0__tar.gz → 1.1.0__tar.gz

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 (65) hide show
  1. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.pre-commit-config.yaml +4 -4
  2. edc_vitals-1.1.0/AUTHORS +2 -0
  3. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/PKG-INFO +3 -2
  4. edc_vitals-1.1.0/edc_vitals/calculators/__init__.py +1 -0
  5. edc_vitals-1.1.0/edc_vitals/calculators/bmi.py +69 -0
  6. edc_vitals-1.1.0/edc_vitals/form_validators/__init__.py +5 -0
  7. edc_vitals-1.1.0/edc_vitals/form_validators/bmi_form_validator_mixin.py +19 -0
  8. edc_vitals-1.0.0/edc_vitals/form_validators/weight_height_bmi_form_validator_mixin.py → edc_vitals-1.1.0/edc_vitals/form_validators/weight_height_with_bmi_form_validator_mixin.py +2 -1
  9. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/model_mixins/weight_height_bmi_model_mixin.py +1 -1
  10. edc_vitals-1.1.0/edc_vitals/tests/tests/test_calculators.py +77 -0
  11. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/test_weight_height_bmi.py +1 -2
  12. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals.egg-info/PKG-INFO +3 -2
  13. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals.egg-info/SOURCES.txt +5 -1
  14. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/pyproject.toml +1 -2
  15. edc_vitals-1.0.0/AUTHORS +0 -1
  16. edc_vitals-1.0.0/edc_vitals/form_validators/__init__.py +0 -2
  17. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.coveragerc +0 -0
  18. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.editorconfig +0 -0
  19. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.github/workflows/build.yml +0 -0
  20. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.gitignore +0 -0
  21. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/.yamllint +0 -0
  22. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/CHANGES +0 -0
  23. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/LICENSE +0 -0
  24. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/MANIFEST.in +0 -0
  25. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/README.rst +0 -0
  26. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/codecov.yml +0 -0
  27. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/__init__.py +0 -0
  28. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/apps.py +0 -0
  29. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +0 -0
  30. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/migrations/__init__.py +0 -0
  31. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/model_mixins/__init__.py +0 -0
  32. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/model_mixins/blood_pressure_model_mixin.py +0 -0
  33. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/__init__.py +0 -0
  34. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/__init__.py +0 -0
  35. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/blood_pressure.py +0 -0
  36. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/heart_rate.py +0 -0
  37. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/height.py +0 -0
  38. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/respiratory_rate.py +0 -0
  39. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/temperature.py +0 -0
  40. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/waist_circumference.py +0 -0
  41. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/models/fields/weight.py +0 -0
  42. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/__init__.py +0 -0
  43. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-aes-local.key +0 -0
  44. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-aes-restricted.key +0 -0
  45. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-rsa-local-private.pem +0 -0
  46. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-rsa-local-public.pem +0 -0
  47. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-rsa-restricted-private.pem +0 -0
  48. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-rsa-restricted-public.pem +0 -0
  49. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-salt-local.key +0 -0
  50. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/etc/user-salt-restricted.key +0 -0
  51. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/models.py +0 -0
  52. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/test_settings.py +0 -0
  53. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/__init__.py +0 -0
  54. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/test_blood_pressure.py +0 -0
  55. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/test_heart_rate.py +0 -0
  56. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/test_respiratory_rate.py +0 -0
  57. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/tests/test_temperature.py +0 -0
  58. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/tests/urls.py +0 -0
  59. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/utils.py +0 -0
  60. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals/validators.py +0 -0
  61. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals.egg-info/dependency_links.txt +0 -0
  62. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals.egg-info/not-zip-safe +0 -0
  63. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/edc_vitals.egg-info/top_level.txt +0 -0
  64. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/runtests.py +0 -0
  65. {edc_vitals-1.0.0 → edc_vitals-1.1.0}/setup.cfg +0 -0
@@ -3,20 +3,20 @@ exclude: tests/etc/user-*
3
3
 
4
4
  repos:
5
5
  - repo: https://github.com/PyCQA/bandit
6
- rev: 1.8.2
6
+ rev: 1.8.3
7
7
  hooks:
8
8
  - id: bandit
9
9
  args:
10
10
  - "-x *test*.py"
11
11
 
12
12
  - repo: https://github.com/psf/black
13
- rev: 24.10.0
13
+ rev: 25.1.0
14
14
  hooks:
15
15
  - id: black
16
16
  language_version: python3.12
17
17
 
18
18
  - repo: https://github.com/pycqa/flake8
19
- rev: 7.1.1
19
+ rev: 7.2.0
20
20
  hooks:
21
21
  - id: flake8
22
22
  args:
@@ -45,7 +45,7 @@ repos:
45
45
  - id: trailing-whitespace
46
46
 
47
47
  - repo: https://github.com/adrienverge/yamllint
48
- rev: v1.35.1
48
+ rev: v1.37.0
49
49
  hooks:
50
50
  - id: yamllint
51
51
  args:
@@ -0,0 +1,2 @@
1
+ Erik van Widenfelt <ew2789@gmail.com>
2
+ Jonathan Willitts (GitHub: https://github.com/JonathanWillitts)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: edc-vitals
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: Classes for BP, weight, etc for clinicedc/edc projects
5
5
  Home-page: https://github.com/clinicedc/edc-vitals
6
6
  Author: Erik van Widenfelt
@@ -19,6 +19,7 @@ Requires-Python: >=3.12
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
21
  License-File: AUTHORS
22
+ Dynamic: license-file
22
23
 
23
24
 
24
25
  |pypi| |actions| |codecov| |downloads|
@@ -0,0 +1 @@
1
+ from .bmi import BMI, CalculatorError, calculate_bmi
@@ -0,0 +1,69 @@
1
+ from dateutil.relativedelta import relativedelta
2
+ from edc_utils import age, get_utcnow
3
+ from edc_utils.round_up import round_half_away_from_zero
4
+
5
+ __all__ = ["calculate_bmi", "BMI", "CalculatorError"]
6
+
7
+
8
+ class CalculatorError(Exception):
9
+ pass
10
+
11
+
12
+ class BMI:
13
+ """Calculate BMI, raise if not adult."""
14
+
15
+ def __init__(
16
+ self,
17
+ weight_kg=None,
18
+ height_cm=None,
19
+ lower_bmi_value=None,
20
+ upper_bmi_value=None,
21
+ dob=None,
22
+ report_datetime=None,
23
+ **kwargs,
24
+ ):
25
+ if not weight_kg or not height_cm:
26
+ raise CalculatorError(f"Unable to calculate BMI. Got {weight_kg}kg, {height_cm}cm")
27
+ if age(dob, report_datetime).years < 18:
28
+ raise CalculatorError("Unable to calculate BMI. Got age<18")
29
+ self.lower = float(lower_bmi_value or 5.0)
30
+ self.upper = float(upper_bmi_value or 75.0)
31
+ self.weight = float(weight_kg)
32
+ self.height = float(height_cm) / 100.0
33
+ self.raw_bmi_value = self.weight / (self.height**2)
34
+ if not (self.lower <= self.raw_bmi_value <= self.upper):
35
+ raise CalculatorError(
36
+ "BMI value is absurd. "
37
+ f"Using {self.weight}kg, {self.height}m. Got {self.value}."
38
+ )
39
+
40
+ @property
41
+ def value(self):
42
+ return round_half_away_from_zero(self.raw_bmi_value, 4)
43
+
44
+
45
+ def calculate_bmi(
46
+ weight_kg=None,
47
+ height_cm=None,
48
+ lower_bmi_value=None,
49
+ upper_bmi_value=None,
50
+ dob=None,
51
+ report_datetime=None,
52
+ **kwargs,
53
+ ):
54
+ """Returns a BMI instance or None.
55
+
56
+ Assumes adult dob (18) if dob not provided."""
57
+ bmi = None
58
+ if height_cm and weight_kg:
59
+ report_datetime = report_datetime or get_utcnow()
60
+ bmi = BMI(
61
+ weight_kg=weight_kg,
62
+ height_cm=height_cm,
63
+ lower_bmi_value=lower_bmi_value,
64
+ upper_bmi_value=upper_bmi_value,
65
+ dob=dob or report_datetime - relativedelta(years=18),
66
+ report_datetime=report_datetime,
67
+ **kwargs,
68
+ )
69
+ return bmi
@@ -0,0 +1,5 @@
1
+ from .blood_pressure_form_validator_mixin import BloodPressureFormValidatorMixin
2
+ from .bmi_form_validator_mixin import BmiFormValidatorMixin
3
+ from .weight_height_with_bmi_form_validator_mixin import (
4
+ WeightHeightBmiFormValidatorMixin,
5
+ )
@@ -0,0 +1,19 @@
1
+ from django import forms
2
+
3
+ from ..calculators import CalculatorError, calculate_bmi
4
+
5
+ __all__ = ["BmiFormValidatorMixin"]
6
+
7
+
8
+ class BmiFormValidatorMixin:
9
+ def validate_bmi(self, **kwargs):
10
+ try:
11
+ bmi = calculate_bmi(
12
+ height_cm=self.cleaned_data.get("height"),
13
+ weight_kg=self.cleaned_data.get("weight"),
14
+ **self.cleaned_data,
15
+ **kwargs,
16
+ )
17
+ except CalculatorError as e:
18
+ raise forms.ValidationError(e)
19
+ return bmi
@@ -1,5 +1,6 @@
1
1
  from django import forms
2
- from edc_reportable import CalculatorError, calculate_bmi
2
+
3
+ from ..calculators import CalculatorError, calculate_bmi
3
4
 
4
5
 
5
6
  class WeightHeightBmiFormValidatorMixin:
@@ -1,6 +1,6 @@
1
1
  from django.db import models
2
- from edc_reportable import calculate_bmi
3
2
 
3
+ from ..calculators import calculate_bmi
4
4
  from ..models import HeightField, WeightField
5
5
 
6
6
 
@@ -0,0 +1,77 @@
1
+ from dateutil.relativedelta import relativedelta
2
+ from django import forms
3
+ from django.test import TestCase, tag
4
+ from edc_constants.constants import BLACK, MALE
5
+ from edc_form_validators import FormValidator
6
+ from edc_utils import get_utcnow
7
+ from edc_utils.round_up import round_half_away_from_zero
8
+
9
+ from edc_vitals.calculators import BMI, CalculatorError, calculate_bmi
10
+ from edc_vitals.form_validators import BmiFormValidatorMixin
11
+
12
+
13
+ class TestCalculators(TestCase):
14
+ @tag("1")
15
+ def test_bmi_calculator(self):
16
+ dob = get_utcnow() - relativedelta(years=25)
17
+ self.assertRaises(CalculatorError, BMI, weight_kg=56, height_cm=None)
18
+ try:
19
+ calculate_bmi(weight_kg=56, height_cm=None, dob=dob)
20
+ except CalculatorError:
21
+ self.fail("CalculatorError unexpectedly raised ")
22
+
23
+ for func in [BMI, calculate_bmi]:
24
+ with self.subTest(func=func):
25
+ self.assertRaises(
26
+ CalculatorError,
27
+ func,
28
+ weight_kg=56,
29
+ height_cm=1.50,
30
+ dob=dob,
31
+ report_datetime=get_utcnow(),
32
+ )
33
+ try:
34
+ bmi = func(
35
+ weight_kg=56, height_cm=150, dob=dob, report_datetime=get_utcnow()
36
+ )
37
+ except CalculatorError as e:
38
+ self.fail(f"CalculatorError unexpectedly raises. Got {e}")
39
+ else:
40
+ self.assertEqual(round_half_away_from_zero(bmi.value, 2), 24.89)
41
+
42
+ @tag("1")
43
+ def test_bmi_form_validator(self):
44
+ data = dict(
45
+ gender=MALE,
46
+ ethnicity=BLACK,
47
+ age_in_years=30,
48
+ )
49
+
50
+ class BmiFormValidator(BmiFormValidatorMixin, FormValidator):
51
+ pass
52
+
53
+ # not enough data
54
+ form_validator = BmiFormValidator(cleaned_data=data)
55
+ bmi = form_validator.validate_bmi()
56
+ self.assertIsNone(bmi)
57
+
58
+ # calculates
59
+ data.update(
60
+ weight=56,
61
+ height=150,
62
+ dob=get_utcnow() - relativedelta(years=30),
63
+ report_datetime=get_utcnow(),
64
+ )
65
+ form_validator = BmiFormValidator(cleaned_data=data)
66
+ bmi = form_validator.validate_bmi()
67
+ self.assertEqual(bmi.value, 24.8889)
68
+
69
+ # calculation error
70
+ data.update(
71
+ weight=56,
72
+ height=1.5,
73
+ dob=get_utcnow() - relativedelta(years=25),
74
+ report_datetime=get_utcnow(),
75
+ )
76
+ form_validator = BmiFormValidator(cleaned_data=data)
77
+ self.assertRaises(forms.ValidationError, form_validator.validate_bmi)
@@ -3,11 +3,10 @@ from decimal import Decimal
3
3
  from dateutil.relativedelta import relativedelta
4
4
  from django import forms
5
5
  from django.test import TestCase
6
+ from edc_reportable.forms import WeightHeightBmiFormValidatorMixin
6
7
  from edc_utils import get_utcnow
7
8
  from edc_utils.round_up import round_half_away_from_zero
8
9
 
9
- from edc_vitals.form_validators import WeightHeightBmiFormValidatorMixin
10
-
11
10
  from ..models import WeightHeightBmi
12
11
 
13
12
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: edc-vitals
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: Classes for BP, weight, etc for clinicedc/edc projects
5
5
  Home-page: https://github.com/clinicedc/edc-vitals
6
6
  Author: Erik van Widenfelt
@@ -19,6 +19,7 @@ Requires-Python: >=3.12
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
21
  License-File: AUTHORS
22
+ Dynamic: license-file
22
23
 
23
24
 
24
25
  |pypi| |actions| |codecov| |downloads|
@@ -22,9 +22,12 @@ edc_vitals.egg-info/SOURCES.txt
22
22
  edc_vitals.egg-info/dependency_links.txt
23
23
  edc_vitals.egg-info/not-zip-safe
24
24
  edc_vitals.egg-info/top_level.txt
25
+ edc_vitals/calculators/__init__.py
26
+ edc_vitals/calculators/bmi.py
25
27
  edc_vitals/form_validators/__init__.py
26
28
  edc_vitals/form_validators/blood_pressure_form_validator_mixin.py
27
- edc_vitals/form_validators/weight_height_bmi_form_validator_mixin.py
29
+ edc_vitals/form_validators/bmi_form_validator_mixin.py
30
+ edc_vitals/form_validators/weight_height_with_bmi_form_validator_mixin.py
28
31
  edc_vitals/migrations/__init__.py
29
32
  edc_vitals/model_mixins/__init__.py
30
33
  edc_vitals/model_mixins/blood_pressure_model_mixin.py
@@ -52,6 +55,7 @@ edc_vitals/tests/etc/user-salt-local.key
52
55
  edc_vitals/tests/etc/user-salt-restricted.key
53
56
  edc_vitals/tests/tests/__init__.py
54
57
  edc_vitals/tests/tests/test_blood_pressure.py
58
+ edc_vitals/tests/tests/test_calculators.py
55
59
  edc_vitals/tests/tests/test_heart_rate.py
56
60
  edc_vitals/tests/tests/test_respiratory_rate.py
57
61
  edc_vitals/tests/tests/test_temperature.py
@@ -13,7 +13,7 @@ extend-exclude = '''^(.*\/)*\b(migrations)\b($|\/.*$)'''
13
13
  [tool.isort]
14
14
  profile = "black"
15
15
  py_version = "312"
16
- skip = [".tox", ".eggs", "migrations"]
16
+ skip = [".tox", ".eggs", "migrations", "_version.py"]
17
17
 
18
18
  [tool.coverage.run]
19
19
  parallel = false
@@ -84,6 +84,5 @@ commands =
84
84
  python --version
85
85
  pip --version
86
86
  pip freeze
87
- pre-commit autoupdate
88
87
  pre-commit run --all-files
89
88
  """
edc_vitals-1.0.0/AUTHORS DELETED
@@ -1 +0,0 @@
1
- Erik van Widenfelt <ew2789@gmail.com>
@@ -1,2 +0,0 @@
1
- from .blood_pressure_form_validator_mixin import BloodPressureFormValidatorMixin
2
- from .weight_height_bmi_form_validator_mixin import WeightHeightBmiFormValidatorMixin
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes