Coverage for baibu/users/phone.py: 100%

12 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-10-06 13:07 +0000

1"""Phone numbers in international (E.164) format. 

2 

3People type numbers with spaces, dashes, dots or brackets, and sometimes 

4``00`` instead of ``+``. :func:`normalize_phone` strips that formatting; 

5:data:`validate_e164` then checks the result is ``+`` followed by the country 

6code and number, at most 15 digits. Numbers in national format (without a 

7country code) are refused rather than guessed. 

8""" 

9 

10import re 

11 

12from django.core.validators import RegexValidator 

13from django.utils.translation import gettext_lazy as _ 

14 

15# Characters people commonly use to group digits. 

16_FORMATTING = re.compile(r"[\s\-.()/]") 

17 

18validate_e164 = RegexValidator( 

19 regex=r"^\+[1-9]\d{6,14}$", 

20 message=_("Enter a phone number in international format, starting with + and the country code."), 

21 code="invalid_phone", 

22) 

23 

24 

25def normalize_phone(value: str | None) -> str: 

26 """Return ``value`` without formatting characters; ``00`` becomes ``+``. 

27 

28 The result is not validated; run :data:`validate_e164` on it. 

29 """ 

30 phone = _FORMATTING.sub("", value or "") 

31 if phone.startswith("00"): 

32 phone = f"+{phone[2:]}" 

33 return phone 

34 

35 

36def mask_phone(phone: str) -> str: 

37 """Hide all but the last two digits, for logs.""" 

38 return f"...{phone[-2:]}" if len(phone) > 2 else "..."