@@ -93,20 +93,25 @@ def accepted_types(self):
9393 """Return a list of MediaType instances, in order of preference."""
9494 header_value = self .headers .get ("Accept" , "*/*" )
9595 return sorted (
96- (MediaType (token ) for token in header_value .split ("," ) if token .strip ()),
97- key = operator .attrgetter ("quality" , "specificity" ),
96+ (
97+ media_type
98+ for token in header_value .split ("," )
99+ if token .strip () and (media_type := MediaType (token )).quality != 0
100+ ),
101+ key = operator .attrgetter ("specificity" , "quality" ),
98102 reverse = True ,
99103 )
100104
101105 def accepted_type (self , media_type ):
102106 """
103107 Return the preferred MediaType instance which matches the given media type.
104108 """
109+ media_type = MediaType (media_type )
105110 return next (
106111 (
107112 accepted_type
108113 for accepted_type in self .accepted_types
109- if accepted_type .match (media_type )
114+ if media_type .match (accepted_type )
110115 ),
111116 None ,
112117 )
@@ -689,13 +694,13 @@ def encode(k, v):
689694
690695class MediaType :
691696 def __init__ (self , media_type_raw_line ):
692- full_type , self .params = parse_header_parameters (
697+ full_type , self ._params = parse_header_parameters (
693698 media_type_raw_line if media_type_raw_line else ""
694699 )
695700 self .main_type , _ , self .sub_type = full_type .partition ("/" )
696701
697702 def __str__ (self ):
698- params_str = "" .join ("; %s=%s" % (k , v ) for k , v in self .params .items ())
703+ params_str = "" .join ("; %s=%s" % (k , v ) for k , v in self ._params .items ())
699704 return "%s%s%s" % (
700705 self .main_type ,
701706 ("/%s" % self .sub_type ) if self .sub_type else "" ,
@@ -705,23 +710,45 @@ def __str__(self):
705710 def __repr__ (self ):
706711 return "<%s: %s>" % (self .__class__ .__qualname__ , self )
707712
708- @property
709- def is_all_types (self ):
710- return self .main_type == "*" and self .sub_type == "*"
713+ @cached_property
714+ def params (self ):
715+ params = self ._params .copy ()
716+ params .pop ("q" , None )
717+ return params
711718
712719 def match (self , other ):
713- if self .is_all_types :
714- return True
715- other = MediaType (other )
716- return self .main_type == other .main_type and self .sub_type in {
717- "*" ,
718- other .sub_type ,
719- }
720+ if not other :
721+ return False
722+
723+ if not isinstance (other , MediaType ):
724+ other = MediaType (other )
725+
726+ main_types = [self .main_type , other .main_type ]
727+ sub_types = [self .sub_type , other .sub_type ]
728+
729+ # Main types and sub types must be defined.
730+ if not all ((* main_types , * sub_types )):
731+ return False
732+
733+ # Main types must match or one be "*", same for sub types.
734+ for this_type , other_type in (main_types , sub_types ):
735+ if this_type != other_type and this_type != "*" and other_type != "*" :
736+ return False
737+
738+ if bool (self .params ) == bool (other .params ):
739+ # If both have params or neither have params, they must be identical.
740+ result = self .params == other .params
741+ else :
742+ # If self has params and other does not, it's a match.
743+ # If other has params and self does not, don't match.
744+ result = bool (self .params or not other .params )
745+
746+ return result
720747
721748 @cached_property
722749 def quality (self ):
723750 try :
724- quality = float (self .params .get ("q" , 1 ))
751+ quality = float (self ._params .get ("q" , 1 ))
725752 except ValueError :
726753 # Discard invalid values.
727754 return 1
@@ -741,7 +768,7 @@ def specificity(self):
741768 return 0
742769 elif self .sub_type == "*" :
743770 return 1
744- elif self .quality == 1 :
771+ elif not self .params :
745772 return 2
746773 return 3
747774
0 commit comments