Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/rest_framework/utils/mediatypes.py: 80%

35 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2Handling of media types, as found in HTTP Content-Type and Accept headers. 

3 

4See https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 

5""" 

6from django.http.multipartparser import parse_header 

7 

8from rest_framework import HTTP_HEADER_ENCODING 

9 

10 

11def media_type_matches(lhs, rhs): 

12 """ 

13 Returns ``True`` if the media type in the first argument <= the 

14 media type in the second argument. The media types are strings 

15 as described by the HTTP spec. 

16 

17 Valid media type strings include: 

18 

19 'application/json; indent=4' 

20 'application/json' 

21 'text/*' 

22 '*/*' 

23 """ 

24 lhs = _MediaType(lhs) 

25 rhs = _MediaType(rhs) 

26 return lhs.match(rhs) 

27 

28 

29def order_by_precedence(media_type_lst): 

30 """ 

31 Returns a list of sets of media type strings, ordered by precedence. 

32 Precedence is determined by how specific a media type is: 

33 

34 3. 'type/subtype; param=val' 

35 2. 'type/subtype' 

36 1. 'type/*' 

37 0. '*/*' 

38 """ 

39 ret = [set(), set(), set(), set()] 

40 for media_type in media_type_lst: 

41 precedence = _MediaType(media_type).precedence 

42 ret[3 - precedence].add(media_type) 

43 return [media_types for media_types in ret if media_types] 

44 

45 

46class _MediaType: 

47 def __init__(self, media_type_str): 

48 self.orig = '' if (media_type_str is None) else media_type_str 

49 self.full_type, self.params = parse_header(self.orig.encode(HTTP_HEADER_ENCODING)) 

50 self.main_type, sep, self.sub_type = self.full_type.partition('/') 

51 

52 def match(self, other): 

53 """Return true if this MediaType satisfies the given MediaType.""" 

54 for key in self.params: 54 ↛ 55line 54 didn't jump to line 55, because the loop on line 54 never started

55 if key != 'q' and other.params.get(key, None) != self.params.get(key, None): 

56 return False 

57 

58 if self.sub_type != '*' and other.sub_type != '*' and other.sub_type != self.sub_type: 

59 return False 

60 

61 if self.main_type != '*' and other.main_type != '*' and other.main_type != self.main_type: 61 ↛ 62line 61 didn't jump to line 62, because the condition on line 61 was never true

62 return False 

63 

64 return True 

65 

66 @property 

67 def precedence(self): 

68 """ 

69 Return a precedence level from 0-3 for the media type given how specific it is. 

70 """ 

71 if self.main_type == '*': 

72 return 0 

73 elif self.sub_type == '*': 73 ↛ 74line 73 didn't jump to line 74, because the condition on line 73 was never true

74 return 1 

75 elif not self.params or list(self.params) == ['q']: 75 ↛ 77line 75 didn't jump to line 77, because the condition on line 75 was never false

76 return 2 

77 return 3 

78 

79 def __str__(self): 

80 ret = "%s/%s" % (self.main_type, self.sub_type) 

81 for key, val in self.params.items(): 

82 ret += "; %s=%s" % (key, val.decode('ascii')) 

83 return ret