Coverage for documents/validators.py: 54%

18 statements  

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

1from urllib.parse import urlparse 

2 

3from django.core.exceptions import ValidationError 

4from django.utils.translation import gettext_lazy as _ 

5 

6 

7def uri_validator(value: str, allowed_schemes: set[str] | None = None) -> None: 

8 """ 

9 Validates that the given value parses as a URI with required components 

10 and optionally restricts to specific schemes. 

11 

12 Args: 

13 value: The URI string to validate 

14 allowed_schemes: Optional set/list of allowed schemes (e.g. {'http', 'https'}). 

15 If None, all schemes are allowed. 

16 

17 Raises: 

18 ValidationError: If the URI is invalid or uses a disallowed scheme 

19 """ 

20 try: 

21 parts = urlparse(value) 

22 if not parts.scheme: 22 ↛ 27line 22 didn't jump to line 27 because the condition on line 22 was always true

23 raise ValidationError( 

24 _(f"Unable to parse URI {value}, missing scheme"), 

25 params={"value": value}, 

26 ) 

27 elif not parts.netloc and not parts.path: 

28 raise ValidationError( 

29 _(f"Unable to parse URI {value}, missing net location or path"), 

30 params={"value": value}, 

31 ) 

32 

33 if allowed_schemes and parts.scheme not in allowed_schemes: 

34 raise ValidationError( 

35 _( 

36 f"URI scheme '{parts.scheme}' is not allowed. Allowed schemes: {', '.join(allowed_schemes)}", 

37 ), 

38 params={"value": value, "scheme": parts.scheme}, 

39 ) 

40 

41 except ValidationError: 

42 raise 

43 except Exception as e: 

44 raise ValidationError( 

45 _(f"Unable to parse URI {value}"), 

46 params={"value": value}, 

47 ) from e 

48 

49 

50def url_validator(value) -> None: 

51 """ 

52 Validates that the given value is a valid HTTP or HTTPS URL. 

53 

54 Args: 

55 value: The URL string to validate 

56 

57 Raises: 

58 ValidationError: If the URL is invalid or not using http/https scheme 

59 """ 

60 uri_validator(value, allowed_schemes={"http", "https"})