Source code for camcops_server.cc_modules.cc_testproviders
"""
camcops_server/cc_modules/cc_testproviders.py
===============================================================================
Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CamCOPS.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
===============================================================================
**Faker test data providers.**
There may be some interest in a Faker Medical community provider if we felt it
was worth the effort.
https://github.com/joke2k/faker/issues/1142
See also duplicate functionality in CRATE: crate_anon/testing/providers.py
"""
import datetime
from cardinal_pythonlib.nhs import generate_random_nhs_number
from faker import Faker
from faker.providers import BaseProvider
import pendulum
from pendulum import DateTime as Pendulum
from typing import Any, List
class NhsNumberProvider(BaseProvider):
@staticmethod
def nhs_number() -> int:
return generate_random_nhs_number()
class ChoiceProvider(BaseProvider):
def random_choice(self, choices: List, **kwargs: Any) -> Any:
"""
Given a list of choices return a random value
"""
choices = self.generator.random.choices(choices, **kwargs)
return choices[0]
# No one is born after this
_max_birth_datetime = Pendulum(year=2000, month=1, day=1, hour=9)
[docs]class ConsistentDateOfBirthProvider(BaseProvider):
"""
Faker date_of_birth calculates from the current time so gives different
results on different days.
"""
def consistent_date_of_birth(self) -> datetime.datetime:
return self.generator.date_between_dates(
date_start=pendulum.date(1900, 1, 1),
date_end=_max_birth_datetime,
)
[docs]class ForenameProvider(BaseProvider):
"""
Return a forename given the sex of the person
"""
def forename(self, sex: str) -> str:
if sex == "M":
return self.generator.first_name_male()
if sex == "F":
return self.generator.first_name_female()
return self.generator.first_name()[:1]
class HeightProvider(BaseProvider):
def height_m(self) -> float:
"""
Return a random patient height in metres
"""
return float(self.generator.random_int(min=145, max=191) / 100.0)
class MassProvider(BaseProvider):
def mass_kg(self) -> float:
"""
Return a random patient mass in kilograms
"""
return float(self.generator.random_int(min=400, max=1000) / 10.0)
[docs]class SexProvider(ChoiceProvider):
"""
Return a random sex, with realistic distribution.
"""
def sex(self) -> str:
return self.random_choice(["M", "F", "X"], weights=[49.8, 49.8, 0.4])
[docs]class ValidPhoneNumberProvider(BaseProvider):
"""
Return a random mobile phone number
"""
# The default Faker phone_number provider for en_GB uses
# https://www.ofcom.org.uk/phones-telecoms-and-internet/information-for-industry/numbering/numbers-for-drama # noqa: E501
# 07700 900000 to 900999 reserved for TV and Radio drama purposes
# but unfortunately the phonenumbers library considers these invalid.
def valid_phone_number(self) -> str:
number = self.generator.random_int(min=7000000000, max=7999999999)
return f"+44{number}"
[docs]class WaistProvider(BaseProvider):
"""
Return a random waist circumference in centimetres
"""
def waist_cm(self) -> float:
return float(self.generator.random_int(min=40, max=130))
def register_all_providers(fake: Faker) -> None:
fake.add_provider(ChoiceProvider)
fake.add_provider(ConsistentDateOfBirthProvider)
fake.add_provider(ForenameProvider)
fake.add_provider(HeightProvider)
fake.add_provider(MassProvider)
fake.add_provider(NhsNumberProvider)
fake.add_provider(ValidPhoneNumberProvider)
fake.add_provider(WaistProvider)
fake.add_provider(SexProvider)