How to use header_value method in Playwright Python

Best Python code snippet using playwright-python

test_acceptparse.py

Source:test_acceptparse.py Github

copy

Full Screen

...2727 {'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},2728 'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',2729 ),2730 ])2731 def test___add___valid_header_value(self, value, value_as_header):2732 result = AcceptCharsetInvalidHeader(header_value='') + value2733 assert isinstance(result, AcceptCharsetValidHeader)2734 assert result.header_value == value_as_header2735 def test___add___other_type_valid_header_value(self):2736 class Other(object):2737 def __str__(self):2738 return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'2739 right_operand = Other()2740 result = AcceptCharsetInvalidHeader(header_value='') + right_operand2741 assert isinstance(result, AcceptCharsetValidHeader)2742 assert result.header_value == str(right_operand)2743 def test___add___AcceptCharsetValidHeader(self):2744 right_operand = AcceptCharsetValidHeader(2745 header_value=', ,utf-7;q=0, \tutf-8;q=1,',2746 )2747 result = AcceptCharsetInvalidHeader(header_value='') + right_operand2748 assert isinstance(result, AcceptCharsetValidHeader)2749 assert result.header_value == right_operand.header_value2750 assert result is not right_operand2751 def test___add___AcceptCharsetNoHeader(self):2752 right_operand = AcceptCharsetNoHeader()2753 result = AcceptCharsetInvalidHeader(header_value='') + right_operand2754 assert isinstance(result, AcceptCharsetNoHeader)2755 assert result is not right_operand2756 def test___add___AcceptCharsetInvalidHeader(self):2757 result = AcceptCharsetInvalidHeader(header_value='') + \2758 AcceptCharsetInvalidHeader(header_value='utf/8')2759 assert isinstance(result, AcceptCharsetNoHeader)2760 def test___bool__(self):2761 instance = AcceptCharsetInvalidHeader(header_value='')2762 returned = bool(instance)2763 assert returned is False2764 @pytest.mark.filterwarnings(IGNORE_CONTAINS)2765 def test___contains__(self):2766 instance = AcceptCharsetInvalidHeader(header_value='')2767 returned = ('char-set' in instance)2768 assert returned is True2769 @pytest.mark.filterwarnings(IGNORE_ITER)2770 def test___iter__(self):2771 instance = AcceptCharsetInvalidHeader(header_value='')2772 returned = list(instance)2773 assert returned == []2774 def test___radd___None(self):2775 result = None + AcceptCharsetInvalidHeader(header_value='')2776 assert isinstance(result, AcceptCharsetNoHeader)2777 @pytest.mark.parametrize('left_operand', [2778 '',2779 [],2780 (),2781 {},2782 'UTF/8',2783 ['UTF/8'],2784 ('UTF/8',),2785 {'UTF/8': 1.0},2786 ])2787 def test___radd___invalid_value(self, left_operand):2788 result = left_operand + AcceptCharsetInvalidHeader(header_value='')2789 assert isinstance(result, AcceptCharsetNoHeader)2790 @pytest.mark.parametrize('str_', ['', 'UTF/8'])2791 def test___radd___other_type_with_invalid___str__(self, str_):2792 class Other(object):2793 def __str__(self):2794 return str_2795 result = Other() + AcceptCharsetInvalidHeader(header_value='')2796 assert isinstance(result, AcceptCharsetNoHeader)2797 @pytest.mark.parametrize('value, value_as_header', [2798 (2799 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',2800 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',2801 ),2802 (2803 [('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],2804 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',2805 ),2806 (2807 (('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),2808 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',2809 ),2810 (2811 {'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},2812 'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',2813 ),2814 ])2815 def test___radd___valid_header_value(self, value, value_as_header):2816 result = value + AcceptCharsetInvalidHeader(header_value='')2817 assert isinstance(result, AcceptCharsetValidHeader)2818 assert result.header_value == value_as_header2819 def test___radd___other_type_valid_header_value(self):2820 class Other(object):2821 def __str__(self):2822 return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'2823 left_operand = Other()2824 result = left_operand + AcceptCharsetInvalidHeader(header_value='')2825 assert isinstance(result, AcceptCharsetValidHeader)2826 assert result.header_value == str(left_operand)2827 def test___repr__(self):2828 instance = AcceptCharsetInvalidHeader(header_value='\x00')2829 assert repr(instance) == '<AcceptCharsetInvalidHeader>'2830 def test___str__(self):2831 instance = AcceptCharsetInvalidHeader(header_value='')2832 assert str(instance) == '<invalid header value>'2833 def test_acceptable_offers(self):2834 instance = AcceptCharsetInvalidHeader(header_value='')2835 returned = instance.acceptable_offers(2836 offers=['utf-8', 'utf-7', 'unicode-1-1'],2837 )2838 assert returned == [2839 ('utf-8', 1.0), ('utf-7', 1.0), ('unicode-1-1', 1.0)2840 ]2841 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)2842 def test_best_match(self):2843 accept = AcceptCharsetInvalidHeader(header_value='')2844 assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'2845 assert accept.best_match([('utf-8', 1), ('iso-8859-5', 0.5)]) == \2846 'utf-8'2847 assert accept.best_match([('utf-8', 0.5), ('iso-8859-5', 1)]) == \2848 'iso-8859-5'2849 assert accept.best_match([('utf-8', 0.5), 'iso-8859-5']) == \2850 'iso-8859-5'2851 assert accept.best_match(2852 [('utf-8', 0.5), 'iso-8859-5'], default_match=True2853 ) == 'iso-8859-5'2854 assert accept.best_match(2855 [('utf-8', 0.5), 'iso-8859-5'], default_match=False2856 ) == 'iso-8859-5'2857 assert accept.best_match([], default_match='fallback') == 'fallback'2858 @pytest.mark.filterwarnings(IGNORE_QUALITY)2859 def test_quality(self):2860 instance = AcceptCharsetInvalidHeader(header_value='')2861 returned = instance.quality(offer='char-set')2862 assert returned == 1.02863class TestCreateAcceptCharsetHeader(object):2864 def test_header_value_is_valid(self):2865 header_value = 'iso-8859-5, unicode-1-1;q=0.8'2866 returned = create_accept_charset_header(header_value=header_value)2867 assert isinstance(returned, AcceptCharsetValidHeader)2868 assert returned.header_value == header_value2869 returned2 = create_accept_charset_header(returned)2870 assert returned2 is not returned2871 assert returned2._header_value == returned._header_value2872 def test_header_value_is_None(self):2873 header_value = None2874 returned = create_accept_charset_header(header_value=header_value)2875 assert isinstance(returned, AcceptCharsetNoHeader)2876 assert returned.header_value == header_value2877 returned2 = create_accept_charset_header(returned)2878 assert returned2 is not returned2879 assert returned2._header_value == returned._header_value2880 @pytest.mark.parametrize('header_value', ['', 'iso-8859-5, unicode/1'])2881 def test_header_value_is_invalid(self, header_value):2882 returned = create_accept_charset_header(header_value=header_value)2883 assert isinstance(returned, AcceptCharsetInvalidHeader)2884 assert returned.header_value == header_value2885 returned2 = create_accept_charset_header(returned)2886 assert returned2 is not returned2887 assert returned2._header_value == returned._header_value2888class TestAcceptCharsetProperty(object):2889 def test_fget_header_is_None(self):2890 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': None})2891 property_ = accept_charset_property()2892 returned = property_.fget(request=request)2893 assert isinstance(returned, AcceptCharsetNoHeader)2894 def test_fget_header_is_valid(self):2895 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})2896 property_ = accept_charset_property()2897 returned = property_.fget(request=request)2898 assert isinstance(returned, AcceptCharsetValidHeader)2899 def test_fget_header_is_invalid(self):2900 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})2901 property_ = accept_charset_property()2902 returned = property_.fget(request=request)2903 assert isinstance(returned, AcceptCharsetInvalidHeader)2904 def test_fset_value_is_None(self):2905 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})2906 property_ = accept_charset_property()2907 property_.fset(request=request, value=None)2908 assert isinstance(request.accept_charset, AcceptCharsetNoHeader)2909 assert 'HTTP_ACCEPT_CHARSET' not in request.environ2910 def test_fset_value_is_invalid(self):2911 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})2912 property_ = accept_charset_property()2913 property_.fset(request=request, value='')2914 assert isinstance(request.accept_charset, AcceptCharsetInvalidHeader)2915 assert request.environ['HTTP_ACCEPT_CHARSET'] == ''2916 def test_fset_value_is_valid(self):2917 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})2918 property_ = accept_charset_property()2919 property_.fset(request=request, value='UTF-7')2920 assert isinstance(request.accept_charset, AcceptCharsetValidHeader)2921 assert request.environ['HTTP_ACCEPT_CHARSET'] == 'UTF-7'2922 @pytest.mark.parametrize('value, value_as_header', [2923 (2924 'utf-8;q=0.5, iso-8859-5;q=0, utf-7',2925 'utf-8;q=0.5, iso-8859-5;q=0, utf-7',2926 ),2927 (2928 [('utf-8', 0.5), ('iso-8859-5', 0.0), 'utf-7'],2929 'utf-8;q=0.5, iso-8859-5;q=0, utf-7',2930 ),2931 (2932 (('utf-8', 0.5), ('iso-8859-5', 0.0), 'utf-7'),2933 'utf-8;q=0.5, iso-8859-5;q=0, utf-7',2934 ),2935 (2936 {'utf-8': 0.5, 'iso-8859-5': 0.0, 'utf-7': 1.0},2937 'utf-7, utf-8;q=0.5, iso-8859-5;q=0',2938 ),2939 ])2940 def test_fset_value_types(self, value, value_as_header):2941 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})2942 property_ = accept_charset_property()2943 property_.fset(request=request, value=value)2944 assert isinstance(request.accept_charset, AcceptCharsetValidHeader)2945 assert request.environ['HTTP_ACCEPT_CHARSET'] == value_as_header2946 def test_fset_other_type_with_valid___str__(self):2947 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})2948 property_ = accept_charset_property()2949 class Other(object):2950 def __str__(self):2951 return 'utf-8;q=0.5, iso-8859-5;q=0, utf-7'2952 value = Other()2953 property_.fset(request=request, value=value)2954 assert isinstance(request.accept_charset, AcceptCharsetValidHeader)2955 assert request.environ['HTTP_ACCEPT_CHARSET'] == str(value)2956 def test_fset_AcceptCharsetNoHeader(self):2957 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})2958 property_ = accept_charset_property()2959 header = AcceptCharsetNoHeader()2960 property_.fset(request=request, value=header)2961 assert isinstance(request.accept_charset, AcceptCharsetNoHeader)2962 assert 'HTTP_ACCEPT_CHARSET' not in request.environ2963 def test_fset_AcceptCharsetValidHeader(self):2964 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})2965 property_ = accept_charset_property()2966 header = AcceptCharsetValidHeader('utf-7')2967 property_.fset(request=request, value=header)2968 assert isinstance(request.accept_charset, AcceptCharsetValidHeader)2969 assert request.environ['HTTP_ACCEPT_CHARSET'] == header.header_value2970 def test_fset_AcceptCharsetInvalidHeader(self):2971 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})2972 property_ = accept_charset_property()2973 header = AcceptCharsetInvalidHeader('')2974 property_.fset(request=request, value=header)2975 assert isinstance(request.accept_charset, AcceptCharsetInvalidHeader)2976 assert request.environ['HTTP_ACCEPT_CHARSET'] == header.header_value2977 def test_fdel_header_key_in_environ(self):2978 request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})2979 property_ = accept_charset_property()2980 property_.fdel(request=request)2981 assert isinstance(request.accept_charset, AcceptCharsetNoHeader)2982 assert 'HTTP_ACCEPT_CHARSET' not in request.environ2983 def test_fdel_header_key_not_in_environ(self):2984 request = Request.blank('/')2985 property_ = accept_charset_property()2986 property_.fdel(request=request)2987 assert isinstance(request.accept_charset, AcceptCharsetNoHeader)2988 assert 'HTTP_ACCEPT_CHARSET' not in request.environ2989class TestAcceptEncoding(object):2990 @pytest.mark.parametrize('value', [2991 '"',2992 '(',2993 ')',2994 '/',2995 ':',2996 ';',2997 '<',2998 '=',2999 '>',3000 '?',3001 '@',3002 '[',3003 '\\',3004 ']',3005 '{',3006 '}',3007 ', ',3008 ', , ',3009 'gzip;q=1.0, identity; q =0.5, *;q=0',3010 ])3011 def test_parse__invalid_header(self, value):3012 with pytest.raises(ValueError):3013 AcceptEncoding.parse(value=value)3014 @pytest.mark.parametrize('value, expected_list', [3015 (',', []),3016 (', ,', []),3017 ('*', [('*', 1.0)]),3018 ("!#$%&'*+-.^_`|~;q=0.5", [("!#$%&'*+-.^_`|~", 0.5)]),3019 ('0123456789', [('0123456789', 1.0)]),3020 (3021 ',,\t foo \t;\t q=0.345,, bar ; Q=0.456 \t, ,\tCHARLIE \t,, ,',3022 [('foo', 0.345), ('bar', 0.456), ('CHARLIE', 1.0)]3023 ),3024 # RFC 7231, section 5.3.43025 ('compress, gzip', [('compress', 1.0), ('gzip', 1.0)]),3026 ('', []),3027 ('*', [('*', 1.0)]),3028 ('compress;q=0.5, gzip;q=1.0', [('compress', 0.5), ('gzip', 1.0)]),3029 (3030 'gzip;q=1.0, identity; q=0.5, *;q=0',3031 [('gzip', 1.0), ('identity', 0.5), ('*', 0.0)],3032 ),3033 ])3034 def test_parse__valid_header(self, value, expected_list):3035 returned = AcceptEncoding.parse(value=value)3036 list_of_returned = list(returned)3037 assert list_of_returned == expected_list3038class TestAcceptEncodingValidHeader(object):3039 def test_parse__inherited(self):3040 returned = AcceptEncodingValidHeader.parse(3041 value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',3042 )3043 list_of_returned = list(returned)3044 assert list_of_returned == \3045 [('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]3046 @pytest.mark.parametrize('header_value', [3047 ', ',3048 'gzip;q=1.0, identity; q =0.5, *;q=0',3049 ])3050 def test___init___invalid_header(self, header_value):3051 with pytest.raises(ValueError):3052 AcceptEncodingValidHeader(header_value=header_value)3053 def test___init___valid_header(self):3054 header_value = ',,\t gzip;q=1.0, identity; q=0, *;q=0.5 \t ,'3055 instance = AcceptEncodingValidHeader(header_value=header_value)3056 assert instance.header_value == header_value3057 assert instance.parsed == [3058 ('gzip', 1.0), ('identity', 0.0), ('*', 0.5),3059 ]3060 assert instance._parsed_nonzero == [('gzip', 1.0), ('*', 0.5)]3061 assert isinstance(instance, AcceptEncoding)3062 def test___add___None(self):3063 left_operand = AcceptEncodingValidHeader(header_value='gzip')3064 result = left_operand + None3065 assert isinstance(result, AcceptEncodingValidHeader)3066 assert result.header_value == left_operand.header_value3067 assert result is not left_operand3068 @pytest.mark.parametrize('right_operand', [3069 ', ',3070 [', '],3071 (', ',),3072 {', ': 1.0},3073 ])3074 def test___add___invalid_value(self, right_operand):3075 left_operand = AcceptEncodingValidHeader(header_value='gzip')3076 result = left_operand + right_operand3077 assert isinstance(result, AcceptEncodingValidHeader)3078 assert result.header_value == left_operand.header_value3079 assert result is not left_operand3080 def test___add___other_type_with_invalid___str__(self):3081 left_operand = AcceptEncodingValidHeader(header_value='gzip')3082 class Other(object):3083 def __str__(self):3084 return ', '3085 right_operand = Other()3086 result = left_operand + right_operand3087 assert isinstance(result, AcceptEncodingValidHeader)3088 assert result.header_value == left_operand.header_value3089 assert result is not left_operand3090 @pytest.mark.parametrize('value', [3091 '',3092 [],3093 (),3094 {},3095 ])3096 def test___add___valid_empty_value(self, value):3097 left_operand = AcceptEncodingValidHeader(header_value='gzip')3098 result = left_operand + value3099 assert isinstance(result, AcceptEncodingValidHeader)3100 assert result.header_value == left_operand.header_value3101 assert result is not left_operand3102 def test___add___other_type_with_valid___str___empty(self):3103 left_operand = AcceptEncodingValidHeader(header_value='gzip')3104 class Other(object):3105 def __str__(self):3106 return ''3107 result = left_operand + Other()3108 assert isinstance(result, AcceptEncodingValidHeader)3109 assert result.header_value == left_operand.header_value3110 assert result is not left_operand3111 @pytest.mark.parametrize('value, value_as_header', [3112 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3113 (3114 ['compress;q=0.5', 'deflate;q=0', '*'],3115 'compress;q=0.5, deflate;q=0, *',3116 ),3117 (3118 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3119 'compress;q=0.5, deflate;q=0, *',3120 ),3121 (3122 ('compress;q=0.5', 'deflate;q=0', '*'),3123 'compress;q=0.5, deflate;q=0, *',3124 ),3125 (3126 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3127 'compress;q=0.5, deflate;q=0, *',3128 ),3129 (3130 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3131 '*, compress;q=0.5, deflate;q=0',3132 ),3133 ])3134 def test___add___valid_value(self, value, value_as_header):3135 header = ',\t ,gzip, identity;q=0.333,'3136 result = AcceptEncodingValidHeader(header_value=header) + value3137 assert isinstance(result, AcceptEncodingValidHeader)3138 assert result.header_value == header + ', ' + value_as_header3139 def test___add___other_type_with_valid___str___not_empty(self):3140 header = ',\t ,gzip, identity;q=0.333,'3141 class Other(object):3142 def __str__(self):3143 return 'compress;q=0.5, deflate;q=0, *'3144 right_operand = Other()3145 result = AcceptEncodingValidHeader(header_value=header) + right_operand3146 assert isinstance(result, AcceptEncodingValidHeader)3147 assert result.header_value == header + ', ' + str(right_operand)3148 def test___add___AcceptEncodingValidHeader_header_value_empty(self):3149 left_operand = AcceptEncodingValidHeader(3150 header_value=',\t ,gzip, identity;q=0.333,'3151 )3152 right_operand = AcceptEncodingValidHeader(header_value='')3153 result = left_operand + right_operand3154 assert isinstance(result, AcceptEncodingValidHeader)3155 assert result.header_value == left_operand.header_value3156 assert result is not left_operand3157 def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):3158 left_operand = AcceptEncodingValidHeader(3159 header_value=',\t ,gzip, identity;q=0.333,',3160 )3161 right_operand = AcceptEncodingValidHeader(3162 header_value='compress;q=0.5, deflate;q=0, *',3163 )3164 result = left_operand + right_operand3165 assert isinstance(result, AcceptEncodingValidHeader)3166 assert result.header_value == left_operand.header_value + ', ' + \3167 right_operand.header_value3168 def test___add___AcceptEncodingNoHeader(self):3169 valid_header_instance = AcceptEncodingValidHeader(header_value='gzip')3170 result = valid_header_instance + AcceptEncodingNoHeader()3171 assert isinstance(result, AcceptEncodingValidHeader)3172 assert result.header_value == valid_header_instance.header_value3173 assert result is not valid_header_instance3174 @pytest.mark.parametrize('header_value', [3175 ', ',3176 'compress;q=1.001',3177 ])3178 def test___add___AcceptEncodingInvalidHeader(self, header_value):3179 valid_header_instance = AcceptEncodingValidHeader(header_value='gzip')3180 result = valid_header_instance + AcceptEncodingInvalidHeader(3181 header_value=header_value,3182 )3183 assert isinstance(result, AcceptEncodingValidHeader)3184 assert result.header_value == valid_header_instance.header_value3185 assert result is not valid_header_instance3186 def test___bool__(self):3187 instance = AcceptEncodingValidHeader(header_value='gzip')3188 returned = bool(instance)3189 assert returned is True3190 @pytest.mark.filterwarnings(IGNORE_CONTAINS)3191 def test___contains__(self):3192 accept = AcceptEncodingValidHeader('gzip, compress')3193 assert 'gzip' in accept3194 assert 'deflate' not in accept3195 for mask in ['*', 'gzip', 'gZIP']:3196 assert 'gzip' in AcceptEncodingValidHeader(mask)3197 @pytest.mark.filterwarnings(IGNORE_ITER)3198 def test___iter__(self):3199 instance = AcceptEncodingValidHeader(3200 header_value='gzip; q=0.5, *; q=0, deflate; q=0.8, compress',3201 )3202 assert list(instance) == ['compress', 'deflate', 'gzip']3203 def test___radd___None(self):3204 right_operand = AcceptEncodingValidHeader(header_value='gzip')3205 result = None + right_operand3206 assert isinstance(result, AcceptEncodingValidHeader)3207 assert result.header_value == right_operand.header_value3208 assert result is not right_operand3209 @pytest.mark.parametrize('left_operand', [3210 ', ',3211 [', '],3212 (', ',),3213 {', ': 1.0},3214 ])3215 def test___radd___invalid_value(self, left_operand):3216 right_operand = AcceptEncodingValidHeader(header_value='gzip')3217 result = left_operand + right_operand3218 assert isinstance(result, AcceptEncodingValidHeader)3219 assert result.header_value == right_operand.header_value3220 assert result is not right_operand3221 def test___radd___other_type_with_invalid___str__(self):3222 right_operand = AcceptEncodingValidHeader(header_value='gzip')3223 class Other(object):3224 def __str__(self):3225 return ', '3226 result = Other() + right_operand3227 assert isinstance(result, AcceptEncodingValidHeader)3228 assert result.header_value == right_operand.header_value3229 assert result is not right_operand3230 @pytest.mark.parametrize('value', [3231 '',3232 [],3233 (),3234 {},3235 ])3236 def test___radd___valid_empty_value(self, value):3237 right_operand = AcceptEncodingValidHeader(header_value='gzip')3238 result = value + right_operand3239 assert isinstance(result, AcceptEncodingValidHeader)3240 assert result.header_value == right_operand.header_value3241 assert result is not right_operand3242 def test___radd___other_type_with_valid___str___empty(self):3243 right_operand = AcceptEncodingValidHeader(header_value='gzip')3244 class Other(object):3245 def __str__(self):3246 return ''3247 result = Other() + right_operand3248 assert isinstance(result, AcceptEncodingValidHeader)3249 assert result.header_value == right_operand.header_value3250 assert result is not right_operand3251 @pytest.mark.parametrize('value, value_as_header', [3252 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3253 (3254 ['compress;q=0.5', 'deflate;q=0', '*'],3255 'compress;q=0.5, deflate;q=0, *',3256 ),3257 (3258 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3259 'compress;q=0.5, deflate;q=0, *',3260 ),3261 (3262 ('compress;q=0.5', 'deflate;q=0', '*'),3263 'compress;q=0.5, deflate;q=0, *',3264 ),3265 (3266 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3267 'compress;q=0.5, deflate;q=0, *',3268 ),3269 (3270 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3271 '*, compress;q=0.5, deflate;q=0',3272 ),3273 ])3274 def test___radd___valid_non_empty_value(self, value, value_as_header):3275 header = ',\t ,gzip, identity;q=0.333,'3276 result = value + AcceptEncodingValidHeader(header_value=header)3277 assert isinstance(result, AcceptEncodingValidHeader)3278 assert result.header_value == value_as_header + ', ' + header3279 def test___radd___other_type_with_valid___str___not_empty(self):3280 header = ',\t ,gzip, identity;q=0.333,'3281 class Other(object):3282 def __str__(self):3283 return 'compress;q=0.5, deflate;q=0, *'3284 left_operand = Other()3285 result = left_operand + AcceptEncodingValidHeader(header_value=header)3286 assert isinstance(result, AcceptEncodingValidHeader)3287 assert result.header_value == str(left_operand) + ', ' + header3288 @pytest.mark.parametrize('header_value, expected_returned', [3289 ('', "<AcceptEncodingValidHeader ('')>"),3290 (3291 ",\t, a ;\t q=0.20 , b ,',",3292 # single quote is valid character in token3293 """<AcceptEncodingValidHeader ("a;q=0.2, b, \'")>"""3294 ),3295 ])3296 def test___repr__(self, header_value, expected_returned):3297 instance = AcceptEncodingValidHeader(header_value=header_value)3298 assert repr(instance) == expected_returned3299 @pytest.mark.parametrize('header_value, expected_returned', [3300 ('', ''),3301 (",\t, a ;\t q=0.20 , b ,',", "a;q=0.2, b, '"),3302 ])3303 def test___str__(self, header_value, expected_returned):3304 instance = AcceptEncodingValidHeader(header_value=header_value)3305 assert str(instance) == expected_returned3306 @pytest.mark.parametrize('header_value, offers, expected_returned', [3307 ('', [], []),3308 ('gzip, compress', [], []),3309 ('', ['gzip', 'deflate'], []),3310 ('', ['gzip', 'identity'], [('identity', 1.0)]),3311 ('compress, deflate, gzip', ['identity'], [('identity', 1.0)]),3312 ('compress, identity;q=0, gzip', ['identity'], []),3313 # *;q=0 does not make sense, but is valid3314 ('*;q=0', ['identity'], []),3315 ('*;q=0, deflate, gzip', ['identity'], []),3316 ('*;q=0, deflate, identity;q=0, gzip', ['identity'], []),3317 (3318 '*;q=0, deflate, identity;q=0.1, gzip',3319 ['identity'],3320 [('identity', 0.1)],3321 ),3322 (3323 'compress, deflate, gzip',3324 ['identity', 'gzip'],3325 [('identity', 1.0), ('gzip', 1.0)],3326 ),3327 (3328 'compress, deflate, gzip',3329 ['gzip', 'identity'],3330 [('gzip', 1.0), ('identity', 1.0)],3331 ),3332 (3333 'IDentity;q=0.5, deflATE;q=0, gZIP;q=0, COMPress',3334 ['GZip', 'DEFlate', 'IDENTity', 'comPRESS'],3335 [('comPRESS', 1.0), ('IDENTity', 0.5)],3336 ),3337 (3338 'compress;q=0, identity, *;q=0.5, identity;q=0, *;q=0, compress',3339 # does not make sense, but is valid3340 ['compress', 'identity', 'deflate', 'gzip'],3341 [('identity', 1.0), ('deflate', 0.5), ('gzip', 0.5)],3342 ),3343 ])3344 def test_acceptable_offers(3345 self, header_value, offers, expected_returned,3346 ):3347 instance = AcceptEncodingValidHeader(header_value=header_value)3348 returned = instance.acceptable_offers(offers=offers)3349 assert returned == expected_returned3350 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3351 def test_best_match(self):3352 accept = AcceptEncodingValidHeader('gzip, iso-8859-5')3353 assert accept.best_match(['gzip', 'iso-8859-5']) == 'gzip'3354 assert accept.best_match(['iso-8859-5', 'gzip']) == 'iso-8859-5'3355 assert accept.best_match([('iso-8859-5', 0.5), 'gzip']) == 'gzip'3356 assert accept.best_match([('iso-8859-5', 0.5), ('gzip', 0.4)]) == \3357 'iso-8859-5'3358 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3359 def test_best_match_with_one_lower_q(self):3360 accept = AcceptEncodingValidHeader('gzip, compress;q=0.5')3361 assert accept.best_match(['gzip', 'compress']) == 'gzip'3362 accept = AcceptEncodingValidHeader('gzip;q=0.5, compress')3363 assert accept.best_match(['gzip', 'compress']) == 'compress'3364 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3365 def test_best_match_with_complex_q(self):3366 accept = AcceptEncodingValidHeader(3367 'gzip, compress;q=0.55, deflate;q=0.59'3368 )3369 assert accept.best_match(['gzip', 'compress']) == 'gzip'3370 accept = AcceptEncodingValidHeader(3371 'gzip;q=0.5, compress;q=0.586, deflate;q=0.596'3372 )3373 assert accept.best_match(['gzip', 'deflate']) == 'deflate'3374 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3375 def test_best_match_mixedcase(self):3376 accept = AcceptEncodingValidHeader(3377 'gZiP; q=0.2, COMPress; Q=0.4, *; q=0.05'3378 )3379 assert accept.best_match(['gzIP']) == 'gzIP'3380 assert accept.best_match(['DeFlAte']) == 'DeFlAte'3381 assert accept.best_match(['deflaTe', 'compRess', 'UtF-8']) == \3382 'compRess'3383 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3384 @pytest.mark.filterwarnings(IGNORE_CONTAINS)3385 def test_best_match_zero_quality(self):3386 assert AcceptEncodingValidHeader('deflate, *;q=0').best_match(3387 ['gzip']3388 ) is None3389 assert 'content-coding' not in AcceptEncodingValidHeader('*;q=0')3390 @pytest.mark.filterwarnings(IGNORE_QUALITY)3391 def test_quality(self):3392 accept = AcceptEncodingValidHeader('gzip')3393 assert accept.quality('gzip') == 13394 accept = AcceptEncodingValidHeader('gzip;q=0.5')3395 assert accept.quality('gzip') == 0.53396 @pytest.mark.filterwarnings(IGNORE_QUALITY)3397 def test_quality_not_found(self):3398 accept = AcceptEncodingValidHeader('gzip')3399 assert accept.quality('compress') is None3400class TestAcceptEncodingNoHeader(object):3401 def test_parse__inherited(self):3402 returned = AcceptEncodingNoHeader.parse(3403 value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',3404 )3405 list_of_returned = list(returned)3406 assert list_of_returned == \3407 [('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]3408 def test___init__(self):3409 instance = AcceptEncodingNoHeader()3410 assert instance.header_value is None3411 assert instance.parsed is None3412 assert instance._parsed_nonzero is None3413 assert isinstance(instance, AcceptEncoding)3414 def test___add___None(self):3415 left_operand = AcceptEncodingNoHeader()3416 result = left_operand + None3417 assert isinstance(result, AcceptEncodingNoHeader)3418 @pytest.mark.parametrize('right_operand', [3419 ', ',3420 [', '],3421 (', ',),3422 {', ': 1.0},3423 ])3424 def test___add___invalid_value(self, right_operand):3425 left_operand = AcceptEncodingNoHeader()3426 result = left_operand + right_operand3427 assert isinstance(result, AcceptEncodingNoHeader)3428 def test___add___other_type_with_invalid___str__(self):3429 left_operand = AcceptEncodingNoHeader()3430 class Other(object):3431 def __str__(self):3432 return ', '3433 right_operand = Other()3434 result = left_operand + right_operand3435 assert isinstance(result, AcceptEncodingNoHeader)3436 @pytest.mark.parametrize('value', [3437 '',3438 [],3439 (),3440 {},3441 ])3442 def test___add___valid_empty_value(self, value):3443 left_operand = AcceptEncodingNoHeader()3444 result = left_operand + value3445 assert isinstance(result, AcceptEncodingValidHeader)3446 assert result.header_value == ''3447 def test___add___other_type_with_valid___str___empty(self):3448 left_operand = AcceptEncodingNoHeader()3449 class Other(object):3450 def __str__(self):3451 return ''3452 result = left_operand + Other()3453 assert isinstance(result, AcceptEncodingValidHeader)3454 assert result.header_value == ''3455 @pytest.mark.parametrize('value, value_as_header', [3456 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3457 (3458 ['compress;q=0.5', 'deflate;q=0', '*'],3459 'compress;q=0.5, deflate;q=0, *',3460 ),3461 (3462 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3463 'compress;q=0.5, deflate;q=0, *',3464 ),3465 (3466 ('compress;q=0.5', 'deflate;q=0', '*'),3467 'compress;q=0.5, deflate;q=0, *',3468 ),3469 (3470 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3471 'compress;q=0.5, deflate;q=0, *',3472 ),3473 (3474 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3475 '*, compress;q=0.5, deflate;q=0',3476 ),3477 ])3478 def test___add___valid_value(self, value, value_as_header):3479 result = AcceptEncodingNoHeader() + value3480 assert isinstance(result, AcceptEncodingValidHeader)3481 assert result.header_value == value_as_header3482 def test___add___other_type_with_valid___str___not_empty(self):3483 class Other(object):3484 def __str__(self):3485 return 'compress;q=0.5, deflate;q=0, *'3486 right_operand = Other()3487 result = AcceptEncodingNoHeader() + right_operand3488 assert isinstance(result, AcceptEncodingValidHeader)3489 assert result.header_value == str(right_operand)3490 def test___add___AcceptEncodingValidHeader_header_value_empty(self):3491 right_operand = AcceptEncodingValidHeader(header_value='')3492 result = AcceptEncodingNoHeader() + right_operand3493 assert isinstance(result, AcceptEncodingValidHeader)3494 assert result.header_value == right_operand.header_value3495 assert result is not right_operand3496 def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):3497 right_operand = AcceptEncodingValidHeader(3498 header_value='compress;q=0.5, deflate;q=0, *',3499 )3500 result = AcceptEncodingNoHeader() + right_operand3501 assert isinstance(result, AcceptEncodingValidHeader)3502 assert result.header_value == right_operand.header_value3503 def test___add___AcceptEncodingNoHeader(self):3504 left_operand = AcceptEncodingNoHeader()3505 right_operand = AcceptEncodingNoHeader()3506 result = left_operand + right_operand3507 assert isinstance(result, AcceptEncodingNoHeader)3508 assert result is not left_operand3509 assert result is not right_operand3510 @pytest.mark.parametrize('header_value', [3511 ', ',3512 'compress;q=1.001',3513 ])3514 def test___add___AcceptEncodingInvalidHeader(self, header_value):3515 left_operand = AcceptEncodingNoHeader()3516 result = left_operand + AcceptEncodingInvalidHeader(3517 header_value=header_value,3518 )3519 assert isinstance(result, AcceptEncodingNoHeader)3520 assert result is not left_operand3521 def test___bool__(self):3522 instance = AcceptEncodingNoHeader()3523 returned = bool(instance)3524 assert returned is False3525 @pytest.mark.filterwarnings(IGNORE_CONTAINS)3526 def test___contains__(self):3527 instance = AcceptEncodingNoHeader()3528 returned = ('content-coding' in instance)3529 assert returned is True3530 @pytest.mark.filterwarnings(IGNORE_ITER)3531 def test___iter__(self):3532 instance = AcceptEncodingNoHeader()3533 returned = list(instance)3534 assert returned == []3535 def test___radd___None(self):3536 right_operand = AcceptEncodingNoHeader()3537 result = None + right_operand3538 assert isinstance(result, AcceptEncodingNoHeader)3539 assert result is not right_operand3540 @pytest.mark.parametrize('left_operand', [3541 ', ',3542 [', '],3543 (', ',),3544 {', ': 1.0},3545 ])3546 def test___radd___invalid_value(self, left_operand):3547 right_operand = AcceptEncodingNoHeader()3548 result = left_operand + right_operand3549 assert isinstance(result, AcceptEncodingNoHeader)3550 assert result is not right_operand3551 def test___radd___other_type_with_invalid___str__(self):3552 right_operand = AcceptEncodingNoHeader()3553 class Other(object):3554 def __str__(self):3555 return ', '3556 result = Other() + right_operand3557 assert isinstance(result, AcceptEncodingNoHeader)3558 assert result is not right_operand3559 @pytest.mark.parametrize('value', [3560 '',3561 [],3562 (),3563 {},3564 ])3565 def test___radd___valid_empty_value(self, value):3566 result = value + AcceptEncodingNoHeader()3567 assert isinstance(result, AcceptEncodingValidHeader)3568 assert result.header_value == ''3569 def test___radd___other_type_with_valid___str___empty(self):3570 class Other(object):3571 def __str__(self):3572 return ''3573 result = Other() + AcceptEncodingNoHeader()3574 assert isinstance(result, AcceptEncodingValidHeader)3575 assert result.header_value == ''3576 @pytest.mark.parametrize('value, value_as_header', [3577 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3578 (3579 ['compress;q=0.5', 'deflate;q=0', '*'],3580 'compress;q=0.5, deflate;q=0, *',3581 ),3582 (3583 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3584 'compress;q=0.5, deflate;q=0, *',3585 ),3586 (3587 ('compress;q=0.5', 'deflate;q=0', '*'),3588 'compress;q=0.5, deflate;q=0, *',3589 ),3590 (3591 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3592 'compress;q=0.5, deflate;q=0, *',3593 ),3594 (3595 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3596 '*, compress;q=0.5, deflate;q=0',3597 ),3598 ])3599 def test___radd___valid_non_empty_value(self, value, value_as_header):3600 result = value + AcceptEncodingNoHeader()3601 assert isinstance(result, AcceptEncodingValidHeader)3602 assert result.header_value == value_as_header3603 def test___radd___other_type_with_valid___str___not_empty(self):3604 class Other(object):3605 def __str__(self):3606 return 'compress;q=0.5, deflate;q=0, *'3607 left_operand = Other()3608 result = left_operand + AcceptEncodingNoHeader()3609 assert isinstance(result, AcceptEncodingValidHeader)3610 assert result.header_value == str(left_operand)3611 def test___repr__(self):3612 instance = AcceptEncodingNoHeader()3613 assert repr(instance) == '<AcceptEncodingNoHeader>'3614 def test___str__(self):3615 instance = AcceptEncodingNoHeader()3616 assert str(instance) == '<no header in request>'3617 def test_acceptable_offers(self):3618 instance = AcceptEncodingNoHeader()3619 returned = instance.acceptable_offers(offers=['a', 'b', 'c'])3620 assert returned == [('a', 1.0), ('b', 1.0), ('c', 1.0)]3621 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3622 def test_best_match(self):3623 accept = AcceptEncodingNoHeader()3624 assert accept.best_match(['gzip', 'compress']) == 'gzip'3625 assert accept.best_match([('gzip', 1), ('compress', 0.5)]) == 'gzip'3626 assert accept.best_match([('gzip', 0.5), ('compress', 1)]) == \3627 'compress'3628 assert accept.best_match([('gzip', 0.5), 'compress']) == 'compress'3629 assert accept.best_match(3630 [('gzip', 0.5), 'compress'], default_match=True3631 ) == 'compress'3632 assert accept.best_match(3633 [('gzip', 0.5), 'compress'], default_match=False3634 ) == 'compress'3635 assert accept.best_match([], default_match='fallback') == 'fallback'3636 @pytest.mark.filterwarnings(IGNORE_QUALITY)3637 def test_quality(self):3638 instance = AcceptEncodingNoHeader()3639 returned = instance.quality(offer='content-coding')3640 assert returned == 1.03641class TestAcceptEncodingInvalidHeader(object):3642 def test_parse__inherited(self):3643 returned = AcceptEncodingInvalidHeader.parse(3644 value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',3645 )3646 list_of_returned = list(returned)3647 assert list_of_returned == \3648 [('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]3649 def test___init__(self):3650 header_value = 'invalid header'3651 instance = AcceptEncodingInvalidHeader(header_value=header_value)3652 assert instance.header_value == header_value3653 assert instance.parsed is None3654 assert instance._parsed_nonzero is None3655 assert isinstance(instance, AcceptEncoding)3656 def test___add___None(self):3657 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3658 result = left_operand + None3659 assert isinstance(result, AcceptEncodingNoHeader)3660 @pytest.mark.parametrize('right_operand', [3661 ', ',3662 [', '],3663 (', ',),3664 {', ': 1.0},3665 ])3666 def test___add___invalid_value(self, right_operand):3667 left_operand = AcceptEncodingInvalidHeader(3668 header_value='invalid header',3669 )3670 result = left_operand + right_operand3671 assert isinstance(result, AcceptEncodingNoHeader)3672 def test___add___other_type_with_invalid___str__(self):3673 left_operand = AcceptEncodingInvalidHeader(3674 header_value='invalid header',3675 )3676 class Other(object):3677 def __str__(self):3678 return ', '3679 right_operand = Other()3680 result = left_operand + right_operand3681 assert isinstance(result, AcceptEncodingNoHeader)3682 @pytest.mark.parametrize('value', [3683 '',3684 [],3685 (),3686 {},3687 ])3688 def test___add___valid_empty_value(self, value):3689 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3690 result = left_operand + value3691 assert isinstance(result, AcceptEncodingValidHeader)3692 assert result.header_value == ''3693 def test___add___other_type_with_valid___str___empty(self):3694 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3695 class Other(object):3696 def __str__(self):3697 return ''3698 result = left_operand + Other()3699 assert isinstance(result, AcceptEncodingValidHeader)3700 assert result.header_value == ''3701 @pytest.mark.parametrize('value, value_as_header', [3702 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3703 (3704 ['compress;q=0.5', 'deflate;q=0', '*'],3705 'compress;q=0.5, deflate;q=0, *',3706 ),3707 (3708 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3709 'compress;q=0.5, deflate;q=0, *',3710 ),3711 (3712 ('compress;q=0.5', 'deflate;q=0', '*'),3713 'compress;q=0.5, deflate;q=0, *',3714 ),3715 (3716 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3717 'compress;q=0.5, deflate;q=0, *',3718 ),3719 (3720 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3721 '*, compress;q=0.5, deflate;q=0',3722 ),3723 ])3724 def test___add___valid_value(self, value, value_as_header):3725 result = AcceptEncodingInvalidHeader(header_value=', ') + value3726 assert isinstance(result, AcceptEncodingValidHeader)3727 assert result.header_value == value_as_header3728 def test___add___other_type_with_valid___str___not_empty(self):3729 class Other(object):3730 def __str__(self):3731 return '*, compress;q=0.5, deflate;q=0'3732 right_operand = Other()3733 result = AcceptEncodingInvalidHeader(header_value=', ') + right_operand3734 assert isinstance(result, AcceptEncodingValidHeader)3735 assert result.header_value == str(right_operand)3736 def test___add___AcceptEncodingValidHeader_header_value_empty(self):3737 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3738 right_operand = AcceptEncodingValidHeader(header_value='')3739 result = left_operand + right_operand3740 assert isinstance(result, AcceptEncodingValidHeader)3741 assert result.header_value == right_operand.header_value3742 assert result is not right_operand3743 def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):3744 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3745 right_operand = AcceptEncodingValidHeader(3746 header_value='compress;q=0.5, deflate;q=0, *',3747 )3748 result = left_operand + right_operand3749 assert isinstance(result, AcceptEncodingValidHeader)3750 assert result.header_value == right_operand.header_value3751 def test___add___AcceptEncodingNoHeader(self):3752 left_operand = AcceptEncodingInvalidHeader(header_value=', ')3753 right_operand = AcceptEncodingNoHeader()3754 result = left_operand + right_operand3755 assert isinstance(result, AcceptEncodingNoHeader)3756 assert result is not right_operand3757 @pytest.mark.parametrize('header_value', [3758 ', ',3759 'compress;q=1.001',3760 ])3761 def test___add___AcceptEncodingInvalidHeader(self, header_value):3762 result = AcceptEncodingInvalidHeader(header_value='gzip;;q=1') + \3763 AcceptEncodingInvalidHeader(header_value=header_value)3764 assert isinstance(result, AcceptEncodingNoHeader)3765 def test___bool__(self):3766 instance = AcceptEncodingInvalidHeader(header_value=', ')3767 returned = bool(instance)3768 assert returned is False3769 @pytest.mark.filterwarnings(IGNORE_CONTAINS)3770 def test___contains__(self):3771 instance = AcceptEncodingInvalidHeader(header_value=', ')3772 returned = ('content-coding' in instance)3773 assert returned is True3774 @pytest.mark.filterwarnings(IGNORE_ITER)3775 def test___iter__(self):3776 instance = AcceptEncodingInvalidHeader(header_value=', ')3777 returned = list(instance)3778 assert returned == []3779 def test___radd___None(self):3780 right_operand = AcceptEncodingInvalidHeader(header_value=', ')3781 result = None + right_operand3782 assert isinstance(result, AcceptEncodingNoHeader)3783 @pytest.mark.parametrize('left_operand', [3784 ', ',3785 [', '],3786 (', ',),3787 {', ': 1.0},3788 ])3789 def test___radd___invalid_value(self, left_operand):3790 right_operand = AcceptEncodingInvalidHeader(header_value='gzip;q= 1')3791 result = left_operand + right_operand3792 assert isinstance(result, AcceptEncodingNoHeader)3793 def test___radd___other_type_with_invalid___str__(self):3794 right_operand = AcceptEncodingInvalidHeader(header_value='gzip;q= 1')3795 class Other(object):3796 def __str__(self):3797 return ', '3798 result = Other() + right_operand3799 assert isinstance(result, AcceptEncodingNoHeader)3800 @pytest.mark.parametrize('value', [3801 '',3802 [],3803 (),3804 {},3805 ])3806 def test___radd___valid_empty_value(self, value):3807 right_operand = AcceptEncodingInvalidHeader(header_value=', ')3808 result = value + right_operand3809 assert isinstance(result, AcceptEncodingValidHeader)3810 assert result.header_value == ''3811 def test___radd___other_type_with_valid___str___empty(self):3812 right_operand = AcceptEncodingInvalidHeader(header_value=', ')3813 class Other(object):3814 def __str__(self):3815 return ''3816 result = Other() + right_operand3817 assert isinstance(result, AcceptEncodingValidHeader)3818 assert result.header_value == ''3819 @pytest.mark.parametrize('value, value_as_header', [3820 ('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),3821 (3822 ['compress;q=0.5', 'deflate;q=0', '*'],3823 'compress;q=0.5, deflate;q=0, *',3824 ),3825 (3826 [('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],3827 'compress;q=0.5, deflate;q=0, *',3828 ),3829 (3830 ('compress;q=0.5', 'deflate;q=0', '*'),3831 'compress;q=0.5, deflate;q=0, *',3832 ),3833 (3834 (('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),3835 'compress;q=0.5, deflate;q=0, *',3836 ),3837 (3838 {'compress': 0.5, 'deflate': 0.0, '*': 1.0},3839 '*, compress;q=0.5, deflate;q=0',3840 ),3841 ])3842 def test___radd___valid_non_empty_value(self, value, value_as_header):3843 result = value + AcceptEncodingInvalidHeader(header_value=', ')3844 assert isinstance(result, AcceptEncodingValidHeader)3845 assert result.header_value == value_as_header3846 def test___radd___other_type_with_valid___str___not_empty(self):3847 class Other(object):3848 def __str__(self):3849 return 'compress;q=0.5, deflate;q=0, *'3850 left_operand = Other()3851 result = left_operand + AcceptEncodingInvalidHeader(header_value=', ')3852 assert isinstance(result, AcceptEncodingValidHeader)3853 assert result.header_value == str(left_operand)3854 def test___repr__(self):3855 instance = AcceptEncodingInvalidHeader(header_value='\x00')3856 assert repr(instance) == '<AcceptEncodingInvalidHeader>'3857 def test___str__(self):3858 instance = AcceptEncodingInvalidHeader(header_value=", ")3859 assert str(instance) == '<invalid header value>'3860 def test_acceptable_offers(self):3861 instance = AcceptEncodingInvalidHeader(header_value=', ')3862 returned = instance.acceptable_offers(offers=['a', 'b', 'c'])3863 assert returned == [('a', 1.0), ('b', 1.0), ('c', 1.0)]3864 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)3865 def test_best_match(self):3866 accept = AcceptEncodingInvalidHeader(header_value=', ')3867 assert accept.best_match(['gzip', 'compress']) == 'gzip'3868 assert accept.best_match([('gzip', 1), ('compress', 0.5)]) == 'gzip'3869 assert accept.best_match([('gzip', 0.5), ('compress', 1)]) == \3870 'compress'3871 assert accept.best_match([('gzip', 0.5), 'compress']) == 'compress'3872 assert accept.best_match(3873 [('gzip', 0.5), 'compress'], default_match=True3874 ) == 'compress'3875 assert accept.best_match(3876 [('gzip', 0.5), 'compress'], default_match=False3877 ) == 'compress'3878 assert accept.best_match([], default_match='fallback') == 'fallback'3879 @pytest.mark.filterwarnings(IGNORE_QUALITY)3880 def test_quality(self):3881 instance = AcceptEncodingInvalidHeader(header_value=', ')3882 returned = instance.quality(offer='content-coding')3883 assert returned == 1.03884class TestCreateAcceptEncodingHeader(object):3885 def test_header_value_is_None(self):3886 header_value = None3887 returned = create_accept_encoding_header(header_value=header_value)3888 assert isinstance(returned, AcceptEncodingNoHeader)3889 assert returned.header_value == header_value3890 returned2 = create_accept_encoding_header(returned)3891 assert returned2 is not returned3892 assert returned2._header_value == returned._header_value3893 def test_header_value_is_valid(self):3894 header_value = 'gzip, identity;q=0.9'3895 returned = create_accept_encoding_header(header_value=header_value)3896 assert isinstance(returned, AcceptEncodingValidHeader)3897 assert returned.header_value == header_value3898 returned2 = create_accept_encoding_header(returned)3899 assert returned2 is not returned3900 assert returned2._header_value == returned._header_value3901 @pytest.mark.parametrize('header_value', [', ', 'gzip;q= 1'])3902 def test_header_value_is_invalid(self, header_value):3903 returned = create_accept_encoding_header(header_value=header_value)3904 assert isinstance(returned, AcceptEncodingInvalidHeader)3905 assert returned.header_value == header_value3906 returned2 = create_accept_encoding_header(returned)3907 assert returned2 is not returned3908 assert returned2._header_value == returned._header_value3909class TestAcceptEncodingProperty(object):3910 def test_fget_header_is_None(self):3911 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': None})3912 property_ = accept_encoding_property()3913 returned = property_.fget(request=request)3914 assert isinstance(returned, AcceptEncodingNoHeader)3915 def test_fget_header_is_valid(self):3916 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})3917 property_ = accept_encoding_property()3918 returned = property_.fget(request=request)3919 assert isinstance(returned, AcceptEncodingValidHeader)3920 def test_fget_header_is_invalid(self):3921 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ', '})3922 property_ = accept_encoding_property()3923 returned = property_.fget(request=request)3924 assert isinstance(returned, AcceptEncodingInvalidHeader)3925 def test_fset_value_is_None(self):3926 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})3927 property_ = accept_encoding_property()3928 property_.fset(request=request, value=None)3929 assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)3930 assert 'HTTP_ACCEPT_ENCODING' not in request.environ3931 def test_fset_value_is_invalid(self):3932 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})3933 property_ = accept_encoding_property()3934 property_.fset(request=request, value=', ')3935 assert isinstance(request.accept_encoding, AcceptEncodingInvalidHeader)3936 assert request.environ['HTTP_ACCEPT_ENCODING'] == ', '3937 def test_fset_value_is_valid(self):3938 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})3939 property_ = accept_encoding_property()3940 property_.fset(request=request, value='compress')3941 assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)3942 assert request.environ['HTTP_ACCEPT_ENCODING'] == 'compress'3943 @pytest.mark.parametrize('value, value_as_header', [3944 (3945 'gzip;q=0.5, compress;q=0, deflate',3946 'gzip;q=0.5, compress;q=0, deflate',3947 ),3948 (3949 [('gzip', 0.5), ('compress', 0.0), 'deflate'],3950 'gzip;q=0.5, compress;q=0, deflate',3951 ),3952 (3953 (('gzip', 0.5), ('compress', 0.0), 'deflate'),3954 'gzip;q=0.5, compress;q=0, deflate',3955 ),3956 (3957 {'gzip': 0.5, 'compress': 0.0, 'deflate': 1.0},3958 'deflate, gzip;q=0.5, compress;q=0',3959 ),3960 ])3961 def test_fset_value_types(self, value, value_as_header):3962 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})3963 property_ = accept_encoding_property()3964 property_.fset(request=request, value=value)3965 assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)3966 assert request.environ['HTTP_ACCEPT_ENCODING'] == value_as_header3967 def test_fset_other_type_with_valid___str__(self):3968 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})3969 property_ = accept_encoding_property()3970 class Other(object):3971 def __str__(self):3972 return 'gzip;q=0.5, compress;q=0, deflate'3973 value = Other()3974 property_.fset(request=request, value=value)3975 assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)3976 assert request.environ['HTTP_ACCEPT_ENCODING'] == str(value)3977 def test_fset_AcceptEncodingNoHeader(self):3978 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})3979 property_ = accept_encoding_property()3980 header = AcceptEncodingNoHeader()3981 property_.fset(request=request, value=header)3982 assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)3983 assert 'HTTP_ACCEPT_ENCODING' not in request.environ3984 def test_fset_AcceptEncodingValidHeader(self):3985 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})3986 property_ = accept_encoding_property()3987 header = AcceptEncodingValidHeader('gzip')3988 property_.fset(request=request, value=header)3989 assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)3990 assert request.environ['HTTP_ACCEPT_ENCODING'] == header.header_value3991 def test_fset_AcceptEncodingInvalidHeader(self):3992 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})3993 property_ = accept_encoding_property()3994 header = AcceptEncodingInvalidHeader(', ')3995 property_.fset(request=request, value=header)3996 assert isinstance(request.accept_encoding, AcceptEncodingInvalidHeader)3997 assert request.environ['HTTP_ACCEPT_ENCODING'] == header.header_value3998 def test_fdel_header_key_in_environ(self):3999 request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})4000 property_ = accept_encoding_property()4001 property_.fdel(request=request)4002 assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)4003 assert 'HTTP_ACCEPT_ENCODING' not in request.environ4004 def test_fdel_header_key_not_in_environ(self):4005 request = Request.blank('/')4006 property_ = accept_encoding_property()4007 property_.fdel(request=request)4008 assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)4009 assert 'HTTP_ACCEPT_ENCODING' not in request.environ4010class TestAcceptLanguage(object):4011 @pytest.mark.parametrize('value', [4012 '',4013 '*s',4014 '*-a',4015 'a-*',4016 'a' * 9,4017 'a-' + 'a' * 9,4018 'a-a-' + 'a' * 9,4019 '-',4020 'a-',4021 '-a',4022 '---',4023 '--a',4024 '1-a',4025 '1-a-a',4026 'en_gb',4027 'en/gb',4028 'foo, bar, baz;q= 0.001',4029 'foo , ,bar,charlie ',4030 ])4031 def test_parse__invalid_header(self, value):4032 with pytest.raises(ValueError):4033 AcceptLanguage.parse(value=value)4034 @pytest.mark.parametrize('value, expected_list', [4035 ('*', [('*', 1.0)]),4036 ('fR;q=0.5', [('fR', 0.5)]),4037 ('zh-Hant;q=0.500', [('zh-Hant', 0.5)]),4038 ('zh-Hans-CN;q=1', [('zh-Hans-CN', 1.0)]),4039 ('de-CH-x-phonebk;q=1.0', [('de-CH-x-phonebk', 1.0)]),4040 ('az-Arab-x-AZE-derbend;q=1.00', [('az-Arab-x-AZE-derbend', 1.0)]),4041 ('zh-CN-a-myExt-x-private;q=1.000', [('zh-CN-a-myExt-x-private', 1.0)]),4042 ('aaaaaaaa', [('aaaaaaaa', 1.0)]),4043 ('aaaaaaaa-a', [('aaaaaaaa-a', 1.0)]),4044 ('aaaaaaaa-aaaaaaaa', [('aaaaaaaa-aaaaaaaa', 1.0)]),4045 ('a-aaaaaaaa-aaaaaaaa', [('a-aaaaaaaa-aaaaaaaa', 1.0)]),4046 ('aaaaaaaa-a-aaaaaaaa', [('aaaaaaaa-a-aaaaaaaa', 1.0)]),4047 (4048 'zh-Hant;q=0.372,zh-CN-a-myExt-x-private;q=0.977,de,*;q=0.000',4049 [4050 ('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),4051 ('de', 1.0), ('*', 0.0)4052 ]4053 ),4054 (4055 ',\t foo \t;\t q=0.345,, bar ; Q=0.456 \t, ,\tcharlie \t,, ,',4056 [('foo', 0.345), ('bar', 0.456), ('charlie', 1.0)]4057 ),4058 # RFC 7230 Section 74059 ('foo,bar', [('foo', 1.0), ('bar', 1.0)]),4060 ('foo, bar,', [('foo', 1.0), ('bar', 1.0)]),4061 # RFC 7230 Errata ID: 41694062 ('foo , ,bar,charlie', [('foo', 1.0), ('bar', 1.0), ('charlie', 1.0)]),4063 ])4064 def test_parse__valid_header(self, value, expected_list):4065 returned = AcceptLanguage.parse(value=value)4066 list_of_returned = list(returned)4067 assert list_of_returned == expected_list4068class TestAcceptLanguageValidHeader(object):4069 @pytest.mark.parametrize('header_value', [4070 '',4071 ', da;q=0.2, en-gb;q=0.3 ',4072 ])4073 def test___init___invalid_header(self, header_value):4074 with pytest.raises(ValueError):4075 AcceptLanguageValidHeader(header_value=header_value)4076 def test___init___valid_header(self):4077 header_value = \4078 'zh-Hant;q=0.372,zh-CN-a-myExt-x-private;q=0.977,de,*;q=0.000'4079 instance = AcceptLanguageValidHeader(header_value=header_value)4080 assert instance.header_value == header_value4081 assert instance.parsed == [4082 ('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),4083 ('de', 1.0), ('*', 0.0)4084 ]4085 assert instance._parsed_nonzero == [4086 ('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),4087 ('de', 1.0)4088 ]4089 assert isinstance(instance, AcceptLanguage)4090 def test___add___None(self):4091 left_operand = AcceptLanguageValidHeader(header_value='en')4092 result = left_operand + None4093 assert isinstance(result, AcceptLanguageValidHeader)4094 assert result.header_value == left_operand.header_value4095 assert result is not left_operand4096 @pytest.mark.parametrize('right_operand', [4097 '',4098 [],4099 (),4100 {},4101 'en_gb',4102 ['en_gb'],4103 ('en_gb',),4104 {'en_gb': 1.0},4105 ',',4106 [','],4107 (',',),4108 {',': 1.0},4109 ])4110 def test___add___invalid_value(self, right_operand):4111 left_operand = AcceptLanguageValidHeader(header_value='en')4112 result = left_operand + right_operand4113 assert isinstance(result, AcceptLanguageValidHeader)4114 assert result.header_value == left_operand.header_value4115 assert result is not left_operand4116 @pytest.mark.parametrize('str_', ['', 'en_gb', ','])4117 def test___add___other_type_with_invalid___str__(self, str_,):4118 left_operand = AcceptLanguageValidHeader(header_value='en')4119 class Other(object):4120 def __str__(self):4121 return str_4122 right_operand = Other()4123 result = left_operand + right_operand4124 assert isinstance(result, AcceptLanguageValidHeader)4125 assert result.header_value == left_operand.header_value4126 assert result is not left_operand4127 @pytest.mark.parametrize('value, value_as_header', [4128 ('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),4129 ([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),4130 ((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),4131 ({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),4132 ])4133 def test___add___valid_value(self, value, value_as_header):4134 header = ',\t ,de, zh-Hans;q=0.333,'4135 result = AcceptLanguageValidHeader(header_value=header) + value4136 assert isinstance(result, AcceptLanguageValidHeader)4137 assert result.header_value == header + ', ' + value_as_header4138 def test___add___other_type_with_valid___str__(self):4139 header = ',\t ,de, zh-Hans;q=0.333,'4140 class Other(object):4141 def __str__(self):4142 return 'en-gb;q=0.5, fr;q=0, es'4143 right_operand = Other()4144 result = AcceptLanguageValidHeader(header_value=header) + right_operand4145 assert isinstance(result, AcceptLanguageValidHeader)4146 assert result.header_value == header + ', ' + str(right_operand)4147 def test___add___AcceptLanguageValidHeader(self):4148 header1 = ',\t ,de, zh-Hans;q=0.333,'4149 header2 = ', ,fr;q=0, \tes;q=1,'4150 result = AcceptLanguageValidHeader(header_value=header1) + \4151 AcceptLanguageValidHeader(header_value=header2)4152 assert isinstance(result, AcceptLanguageValidHeader)4153 assert result.header_value == header1 + ', ' + header24154 def test___add___AcceptLanguageNoHeader(self):4155 valid_header_instance = AcceptLanguageValidHeader(header_value='es')4156 result = valid_header_instance + AcceptLanguageNoHeader()4157 assert isinstance(result, AcceptLanguageValidHeader)4158 assert result.header_value == valid_header_instance.header_value4159 assert result is not valid_header_instance4160 @pytest.mark.parametrize('header_value', ['', 'en_gb', ','])4161 def test___add___AcceptLanguageInvalidHeader(self, header_value):4162 valid_header_instance = AcceptLanguageValidHeader(4163 header_value='header',4164 )4165 result = valid_header_instance + AcceptLanguageInvalidHeader(4166 header_value=header_value,4167 )4168 assert isinstance(result, AcceptLanguageValidHeader)4169 assert result.header_value == valid_header_instance.header_value4170 assert result is not valid_header_instance4171 def test___bool__(self):4172 instance = AcceptLanguageValidHeader(header_value='valid-header')4173 returned = bool(instance)4174 assert returned is True4175 @pytest.mark.parametrize('header_value, offer', [4176 ('*', 'da'),4177 ('da', 'DA'),4178 ('en', 'en-gb'),4179 ('en-gb', 'en-gb'),4180 ('en-gb', 'en'),4181 ('en-gb', 'en_GB'),4182 ])4183 @pytest.mark.filterwarnings(IGNORE_CONTAINS)4184 def test___contains___in(self, header_value, offer):4185 instance = AcceptLanguageValidHeader(header_value=header_value)4186 assert offer in instance4187 @pytest.mark.parametrize('header_value, offer', [4188 ('en-gb', 'en-us'),4189 ('en-gb', 'fr-fr'),4190 ('en-gb', 'fr'),4191 ('en', 'fr-fr'),4192 ])4193 @pytest.mark.filterwarnings(IGNORE_CONTAINS)4194 def test___contains___not_in(self, header_value, offer):4195 instance = AcceptLanguageValidHeader(header_value=header_value)4196 assert offer not in instance4197 @pytest.mark.parametrize('header_value, expected_list', [4198 ('fr;q=0, jp;q=0', []),4199 ('en-gb, da', ['en-gb', 'da']),4200 ('en-gb;q=0.5, da;q=0.5', ['en-gb', 'da']),4201 (4202 'de;q=0.8, de-DE-1996;q=0.5, de-Deva;q=0, de-Latn-DE',4203 ['de-Latn-DE', 'de', 'de-DE-1996']4204 ),4205 # __iter__ is currently a simple filter for the ranges in the header4206 # with non-0 qvalues, and does not attempt to account for the special4207 # meanings of q=0 and *:4208 ('en-gb;q=0, *', ['*']),4209 ('de, de;q=0', ['de']),4210 ])4211 @pytest.mark.filterwarnings(IGNORE_ITER)4212 def test___iter__(self, header_value, expected_list):4213 instance = AcceptLanguageValidHeader(header_value=header_value)4214 assert list(instance) == expected_list4215 def test___radd___None(self):4216 right_operand = AcceptLanguageValidHeader(header_value='en')4217 result = None + right_operand4218 assert isinstance(result, AcceptLanguageValidHeader)4219 assert result.header_value == right_operand.header_value4220 assert result is not right_operand4221 @pytest.mark.parametrize('left_operand', [4222 '',4223 [],4224 (),4225 {},4226 'en_gb',4227 ['en_gb'],4228 ('en_gb',),4229 {'en_gb': 1.0},4230 ',',4231 [','],4232 (',',),4233 {',': 1.0},4234 ])4235 def test___radd___invalid_value(self, left_operand):4236 right_operand = AcceptLanguageValidHeader(header_value='en')4237 result = left_operand + right_operand4238 assert isinstance(result, AcceptLanguageValidHeader)4239 assert result.header_value == right_operand.header_value4240 assert result is not right_operand4241 @pytest.mark.parametrize('str_', ['', 'en_gb', ','])4242 def test___radd___other_type_with_invalid___str__(self, str_,):4243 right_operand = AcceptLanguageValidHeader(header_value='en')4244 class Other(object):4245 def __str__(self):4246 return str_4247 result = Other() + right_operand4248 assert isinstance(result, AcceptLanguageValidHeader)4249 assert result.header_value == right_operand.header_value4250 assert result is not right_operand4251 @pytest.mark.parametrize('value, value_as_header', [4252 ('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),4253 ([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),4254 ((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),4255 ({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),4256 ])4257 def test___radd___valid_value(self, value, value_as_header):4258 right_operand = AcceptLanguageValidHeader(4259 header_value=',\t ,de, zh-Hans;q=0.333,',4260 )4261 result = value + right_operand4262 assert isinstance(result, AcceptLanguageValidHeader)4263 assert result.header_value == value_as_header + ', ' + \4264 right_operand.header_value4265 def test___radd___other_type_with_valid___str__(self):4266 right_operand = AcceptLanguageValidHeader(4267 header_value=',\t ,de, zh-Hans;q=0.333,',4268 )4269 class Other(object):4270 def __str__(self):4271 return 'en-gb;q=0.5, fr;q=0, es'4272 left_operand = Other()4273 result = left_operand + right_operand4274 assert isinstance(result, AcceptLanguageValidHeader)4275 assert result.header_value == str(left_operand) + ', ' + \4276 right_operand.header_value4277 def test___repr__(self):4278 instance = AcceptLanguageValidHeader(4279 header_value=',da;q=0.200,en-gb;q=0.300',4280 )4281 assert repr(instance) == \4282 "<AcceptLanguageValidHeader ('da;q=0.2, en-gb;q=0.3')>"4283 def test___str__(self):4284 header_value = \4285 ', \t,de;q=0.000 \t, es;q=1.000, zh, jp;q=0.210 ,'4286 instance = AcceptLanguageValidHeader(header_value=header_value)4287 assert str(instance) == 'de;q=0, es, zh, jp;q=0.21'4288 @pytest.mark.parametrize(4289 'header_value, language_tags, expected_returned',4290 [4291 # Example from RFC 4647, Section 3.44292 (4293 'de-de',4294 ['de', 'de-DE-1996', 'de-Deva', 'de-Latn-DE'],4295 [('de-DE-1996', 1.0)]4296 ),4297 # Empty `language_tags`4298 (4299 'a',4300 [],4301 []4302 ),4303 # No matches4304 (4305 'a, b',4306 ['c', 'd'],4307 []4308 ),4309 # Several ranges and tags, no matches4310 (4311 'a-b;q=0.9, c-d;q=0.5, e-f',4312 ('a', 'b', 'c', 'd', 'e', 'f'),4313 []4314 ),4315 # Case-insensitive match4316 (4317 'foO, BaR',4318 ['foo', 'bar'],4319 [('foo', 1.0), ('bar', 1.0)]4320 ),4321 # If a tag matches a non-'*' range with q=0, tag is filtered out4322 (4323 'b-c, a, b;q=0, d;q=0',4324 ['b-c', 'a', 'b-c-d', 'd-e-f'],4325 [('a', 1.0)]4326 ),4327 # Match if a range exactly equals a tag4328 (4329 'd-e-f',4330 ['a-b-c', 'd-e-f'],4331 [('d-e-f', 1.0)]4332 ),4333 # Match if a range exactly equals a prefix of the tag such that the4334 # first character following the prefix is '-'4335 (4336 'a-b-c-d, a-b-c-d-e, a-b-c-d-f-g-h',4337 ['a-b-c-d-f-g'],4338 [('a-b-c-d-f-g', 1.0)]4339 ),4340 # '*', when it is the only range in the header, matches everything4341 (4342 '*',4343 ['a', 'b'],4344 [('a', 1.0), ('b', 1.0)]4345 ),4346 # '*' range matches only tags not matched by any other range4347 (4348 '*;q=0.2, a;q=0.5, b',4349 ['a-a', 'b-a', 'c-a', 'd-a'],4350 [('b-a', 1.0), ('a-a', 0.5), ('c-a', 0.2), ('d-a', 0.2)]4351 ),4352 # '*' range without a qvalue gives a matched qvalue of 1.04353 (4354 'a;q=0.5, b, *',4355 ['a-a', 'b-a', 'c-a', 'd-a'],4356 [('b-a', 1.0), ('c-a', 1.0), ('d-a', 1.0), ('a-a', 0.5)]4357 ),4358 # The qvalue for the '*' range works the same way as qvalues for4359 # non-'*' ranges.4360 (4361 'a;q=0.5, *;q=0.9',4362 # (meaning: prefer anything other than 'a', with 'a' as a4363 # fallback)4364 ['a', 'b'],4365 [('b', 0.9), ('a', 0.5)]4366 ),4367 # More than one range matching the same tag: range with the highest4368 # qvalue is matched4369 (4370 'a-b-c;q=0.7, a;q=0.9, a-b;q=0.8',4371 ['a-b-c'],4372 [('a-b-c', 0.9)]4373 ),4374 # More than one range with the same qvalue matching the same tag:4375 # the range in an earlier position in the header is matched4376 (4377 'a-b-c;q=0.7, a;q=0.9, b;q=0.9, a-b;q=0.9',4378 ['a-b-c', 'b'],4379 [('a-b-c', 0.9), ('b', 0.9)]4380 ),4381 # The returned list of tuples is sorted in descending order of qvalue4382 (4383 'a;q=0.7, b;q=0.3, c, d;q=0.5',4384 ['d', 'c', 'b', 'a'],4385 [('c', 1.0), ('a', 0.7), ('d', 0.5), ('b', 0.3)]4386 ),4387 # When qvalues are the same, the tag whose matched range appears4388 # earlier in the header comes first4389 (4390 'a, c, b',4391 ['b', 'a', 'c'],4392 [('a', 1.0), ('c', 1.0), ('b', 1.0)]4393 ),4394 # When many tags match the same range (so same qvalue and same4395 # matched range position in header), they are returned in order of4396 # their position in the `language_tags` argument4397 (4398 'a',4399 ['a-b', 'a', 'a-b-c'],4400 [('a-b', 1.0), ('a', 1.0), ('a-b-c', 1.0)]4401 ),4402 # When a non-'*' range appears in the header more than once, we use4403 # the first one for matching and ignore the others4404 (4405 'a;q=0.5, c;q=0.6, b;q=0.7, c;q=0.9',4406 ['a', 'b', 'c'],4407 [('b', 0.7), ('c', 0.6), ('a', 0.5)]4408 ),4409 (4410 'a, b, c;q=0.5, c;q=0',4411 ['a-a', 'b-a', 'c-a'],4412 [('a-a', 1.0), ('b-a', 1.0), ('c-a', 0.5)]4413 ),4414 (4415 'a;q=0.5, c;q=0.9, b;q=0.9, c;q=0.9',4416 ['a', 'b', 'c'],4417 [('c', 0.9), ('b', 0.9), ('a', 0.5)]4418 ),4419 # When the '*' range appears in the header more than once, we use4420 # the first one for matching and ignore the others4421 (4422 'a;q=0.5, *;q=0.6, b;q=0.7, *;q=0.9',4423 ['a', 'b', 'c'],4424 [('b', 0.7), ('c', 0.6), ('a', 0.5)]4425 ),4426 (4427 'a, b, *;q=0.5, *;q=0',4428 ['a-a', 'b-a', 'c-a'],4429 [('a-a', 1.0), ('b-a', 1.0), ('c-a', 0.5)]4430 ),4431 (4432 'a;q=0.5, *;q=0.9, b;q=0.9, *;q=0.9',4433 ['a', 'b', 'c'],4434 [('c', 0.9), ('b', 0.9), ('a', 0.5)]4435 ),4436 # Both '*' and non-'*' ranges appearing more than once4437 (4438 'a-b;q=0.5, c-d, *, a-b, c-d;q=0.3, *;q=0',4439 ['a-b-c', 'c-d-e', 'e-f-g'],4440 [('c-d-e', 1.0), ('e-f-g', 1.0), ('a-b-c', 0.5)]4441 ),4442 ]4443 )4444 def test_basic_filtering(4445 self, header_value, language_tags, expected_returned,4446 ):4447 instance = AcceptLanguageValidHeader(header_value=header_value)4448 returned = instance.basic_filtering(language_tags=language_tags)4449 assert returned == expected_returned4450 @pytest.mark.parametrize(4451 'header_value, offers, default_match, expected_returned', [4452 ('bar, *;q=0', ['foo'], None, None),4453 ('en-gb, sr-Cyrl', ['sr-Cyrl', 'en-gb'], None, 'sr-Cyrl'),4454 ('en-gb, sr-Cyrl', ['en-gb', 'sr-Cyrl'], None, 'en-gb'),4455 ('en-gb, sr-Cyrl', [('sr-Cyrl', 0.5), 'en-gb'], None, 'en-gb'),4456 (4457 'en-gb, sr-Cyrl', [('sr-Cyrl', 0.5), ('en-gb', 0.4)], None,4458 'sr-Cyrl',4459 ),4460 ('en-gb, sr-Cyrl;q=0.5', ['en-gb', 'sr-Cyrl'], None, 'en-gb'),4461 ('en-gb;q=0.5, sr-Cyrl', ['en-gb', 'sr-Cyrl'], None, 'sr-Cyrl'),4462 (4463 'en-gb, sr-Cyrl;q=0.55, es;q=0.59', ['en-gb', 'sr-Cyrl'], None,4464 'en-gb',4465 ),4466 (4467 'en-gb;q=0.5, sr-Cyrl;q=0.586, es-419;q=0.597',4468 ['en-gb', 'es-419'], None, 'es-419',4469 ),4470 ]4471 )4472 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)4473 def test_best_match(4474 self, header_value, offers, default_match, expected_returned,4475 ):4476 instance = AcceptLanguageValidHeader(header_value=header_value)4477 returned = instance.best_match(4478 offers=offers, default_match=default_match,4479 )4480 assert returned == expected_returned4481 def test_lookup_default_tag_and_default_cannot_both_be_None(self):4482 instance = AcceptLanguageValidHeader(header_value='valid-header')4483 with pytest.raises(TypeError):4484 instance.lookup(4485 language_tags=['tag'],4486 default_range='language-range',4487 default_tag=None,4488 default=None,4489 )4490 def test_lookup_default_range_cannot_be_asterisk(self):4491 instance = AcceptLanguageValidHeader(header_value='valid-header')4492 with pytest.raises(ValueError):4493 instance.lookup(4494 language_tags=['tag'],4495 default_range='*',4496 default_tag='default-tag',4497 default=None,4498 )4499 @pytest.mark.parametrize(4500 (4501 'header_value, language_tags, default_range, default_tag, default'4502 ', expected'4503 ),4504 [4505 # Each language range in the header is considered in turn, in4506 # descending order of qvalue4507 (4508 'aA;q=0.3, Bb, cC;q=0.7',4509 ['Aa', 'bB', 'Cc'],4510 None, 'default-tag', None,4511 'bB',4512 ),4513 # For ranges with the same qvalue, position in header is the4514 # tiebreaker.4515 (4516 'bB-Cc;q=0.8, aA;q=0.9, Bb;q=0.9',4517 ['bb', 'aa'],4518 None, 'default-tag', None,4519 'aa',4520 ),4521 # Each language range represents the most specific tag that is an4522 # acceptable match. Examples from RFC 4647, section 3.4, first4523 # paragraph:4524 (4525 'de-ch',4526 ['de-CH-1996', 'de-CH', 'de'],4527 None, 'default-tag', None,4528 'de-CH',4529 ),4530 (4531 'de-ch',4532 ['de-CH-1996', 'de'],4533 None, 'default-tag', None,4534 'de',4535 ),4536 # The language range is progressively truncated from the end until4537 # a matching language tag is located. From the example of a Lookup4538 # Fallback Pattern in RFC 4647, section 3.4:4539 (4540 'zh-Hant-CN-x-private1-private2',4541 [4542 'zh-Hant-CN-x-private1-private2',4543 'zh-Hant-CN-x-private1',4544 'zh-Hant-CN-x',4545 'zh-Hant-CN',4546 'zh-Hant',4547 'zh',4548 ],4549 None, 'default-tag', None,4550 'zh-Hant-CN-x-private1-private2',4551 ),4552 (4553 'zh-Hant-CN-x-private1-private2',4554 [4555 'zh-Hant-CN-x-private1',4556 'zh-Hant-CN-x',4557 'zh-Hant-CN',4558 'zh-Hant',4559 'zh',4560 ],4561 None, 'default-tag', None,4562 'zh-Hant-CN-x-private1',4563 ),4564 (4565 'zh-Hant-CN-x-private1-private2',4566 [4567 'zh-Hant-CN-x',4568 'zh-Hant-CN',4569 'zh-Hant',4570 'zh',4571 ],4572 None, 'default-tag', None,4573 'zh-Hant-CN',4574 ),4575 (4576 'zh-Hant-CN-x-private1-private2',4577 [4578 'zh-Hant-CN',4579 'zh-Hant',4580 'zh',4581 ],4582 None, 'default-tag', None,4583 'zh-Hant-CN',4584 ),4585 (4586 'zh-Hant-CN-x-private1-private2',4587 [4588 'zh-Hant',4589 'zh',4590 ],4591 None, 'default-tag', None,4592 'zh-Hant',4593 ),4594 (4595 'zh-Hant-CN-x-private1-private2',4596 ['zh'],4597 None, 'default-tag', None,4598 'zh',4599 ),4600 (4601 'zh-Hant-CN-x-private1-private2',4602 ['some-other-tag-1', 'some-other-tag-2'],4603 None, 'default-tag', None,4604 'default-tag',4605 ),4606 # Further tests to check that single-letter or -digit subtags are4607 # removed at the same time as their closest trailing subtag:4608 (4609 'AA-T-subtag',4610 ['Aa-t', 'aA'],4611 None, 'default-tag', None,4612 'aA',4613 ),4614 (4615 'AA-1-subtag',4616 ['aa-1', 'aA'],4617 None, 'default-tag', None,4618 'aA',4619 ),4620 (4621 'Aa-P-subtag-8-subtag',4622 ['Aa-p-subtag-8', 'Aa-p', 'aA'],4623 None, 'default-tag', None,4624 'aA',4625 ),4626 (4627 'aA-3-subTag-C-subtag',4628 ['aA-3-subtag-c', 'aA-3', 'aA'],4629 None, 'default-tag', None,4630 'aA',4631 ),4632 # Test that single-letter or -digit subtag in first position works4633 # as expected4634 (4635 'T-subtag',4636 ['t-SubTag', 'another'],4637 None, 'default-tag', None,4638 't-SubTag',4639 ),4640 (4641 'T-subtag',4642 ['another'],4643 None, 'default-tag', None,4644 'default-tag',4645 ),4646 # If the language range "*" is followed by other language ranges,4647 # it is skipped.4648 (4649 '*, Aa-aA-AA',4650 ['bb', 'aA'],4651 None, 'default-tag', None,4652 'aA',4653 ),4654 # If the language range "*" is the only one in the header, lookup4655 # proceeds to the default arguments.4656 (4657 '*',4658 ['bb', 'aa'],4659 None, 'default-tag', None,4660 'default-tag',4661 ),4662 # If no other language range follows the "*" in the header, lookup4663 # proceeds to the default arguments.4664 (4665 'dd, cc, *',4666 ['bb', 'aa'],4667 None, 'default-tag', None,4668 'default-tag',4669 ),4670 # If a non-'*' range has q=0, any tag that matches the range4671 # exactly (without subtag truncation) is not acceptable.4672 (4673 'aa, bB-Cc-DD;q=0, bB-Cc, cc',4674 ['bb', 'bb-Cc-DD', 'bb-cC-dd', 'Bb-cc', 'bb-cC-dd'],4675 None, 'default-tag', None,4676 'Bb-cc',4677 ),4678 # ;q=0 and ;q={not 0} both in header: q=0 takes precedence and4679 # makes the exact match not acceptable, but the q={not 0} means4680 # that tags can still match after subtag truncation.4681 (4682 'aa, bB-Cc-DD;q=0.9, cc, Bb-cC-dD;q=0',4683 ['bb', 'Bb-Cc', 'Bb-cC-dD'],4684 None, 'default-tag', None,4685 'Bb-Cc',4686 ),4687 # If none of the ranges in the header match any of the language4688 # tags, and the `default_range` argument is not None and does not4689 # match any q=0 range in the header, we search through it by4690 # progressively truncating from the end, as we do with the ranges4691 # in the header. Example from RFC 4647, section 3.4.1:4692 (4693 'fr-FR, zh-Hant',4694 [4695 'fr-FR',4696 'fr',4697 'zh-Hant',4698 'zh',4699 'ja-JP',4700 'ja',4701 ],4702 'ja-JP', 'default-tag', None,4703 'fr-FR',4704 ),4705 (4706 'fr-FR, zh-Hant',4707 [4708 'fr',4709 'zh-Hant',4710 'zh',4711 'ja-JP',4712 'ja',4713 ],4714 'ja-JP', 'default-tag', None,4715 'fr',4716 ),4717 (4718 'fr-FR, zh-Hant',4719 [4720 'zh-Hant',4721 'zh',4722 'ja-JP',4723 'ja',4724 ],4725 'ja-JP', 'default-tag', None,4726 'zh-Hant',4727 ),4728 (4729 'fr-FR, zh-Hant',4730 [4731 'zh',4732 'ja-JP',4733 'ja',4734 ],4735 'ja-JP', 'default-tag', None,4736 'zh',4737 ),4738 (4739 'fr-FR, zh-Hant',4740 [4741 'ja-JP',4742 'ja',4743 ],4744 'ja-JP', 'default-tag', None,4745 'ja-JP',4746 ),4747 (4748 'fr-FR, zh-Hant',4749 ['ja'],4750 'ja-JP', 'default-tag', None,4751 'ja',4752 ),4753 (4754 'fr-FR, zh-Hant',4755 ['some-other-tag-1', 'some-other-tag-2'],4756 'ja-JP', 'default-tag', None,4757 'default-tag',4758 ),4759 # If none of the ranges in the header match the language tags, the4760 # `default_range` argument is not None, and there is a '*;q=0'4761 # range in the header, then the `default_range` and its substrings4762 # from subtag truncation are not acceptable.4763 (4764 'aa-bb, cc-dd, *;q=0',4765 ['ee-ff', 'ee'],4766 'ee-ff', None, 'default',4767 'default',4768 ),4769 # If none of the ranges in the header match the language tags, the4770 # `default_range` argument is not None, and the argument exactly4771 # matches a non-'*' range in the header with q=0 (without fallback4772 # subtag truncation), then the `default_range` itself is not4773 # acceptable...4774 (4775 'aa-bb, cc-dd, eE-Ff;q=0',4776 ['Ee-fF'],4777 'EE-FF', 'default-tag', None,4778 'default-tag',4779 ),4780 # ...but it should still be searched with subtag truncation,4781 # because its substrings other than itself are still acceptable:4782 (4783 'aa-bb, cc-dd, eE-Ff-Gg;q=0',4784 ['Ee', 'Ee-fF-gG', 'Ee-fF'],4785 'EE-FF-GG', 'default-tag', None,4786 'Ee-fF',4787 ),4788 (4789 'aa-bb, cc-dd, eE-Ff-Gg;q=0',4790 ['Ee-fF-gG', 'Ee'],4791 'EE-FF-GG', 'default-tag', None,4792 'Ee',4793 ),4794 # If `default_range` only has one subtag, then no subtag truncation4795 # is possible, and we proceed to `default-tag`:4796 (4797 'aa-bb, cc-dd, eE;q=0',4798 ['Ee'],4799 'EE', 'default-tag', None,4800 'default-tag',4801 ),4802 # If the `default_range` argument would only match a non-'*' range4803 # in the header with q=0 exactly if the `default_range` had subtags4804 # from the end truncated, then it is acceptable, and we attempt to4805 # match it with the language tags using subtag truncation. However,4806 # the tag equivalent of the range with q=0 would be considered not4807 # acceptable and ruled out, if we reach it during the subtag4808 # truncation search.4809 (4810 'aa-bb, cc-dd, eE-Ff;q=0',4811 ['Ee-fF', 'Ee-fF-33', 'ee'],4812 'EE-FF-33', 'default-tag', None,4813 'Ee-fF-33',4814 ),4815 (4816 'aa-bb, cc-dd, eE-Ff;q=0',4817 ['Ee-fF', 'eE'],4818 'EE-FF-33', 'default-tag', None,4819 'eE',4820 ),4821 # If none of the ranges in the header match, the `default_range`4822 # argument is None or does not match, and the `default_tag`4823 # argument is not None and does not match any range in the header4824 # with q=0, then the `default_tag` argument is returned.4825 (4826 'aa-bb, cc-dd',4827 ['ee-ff', 'ee'],4828 None, 'default-tag', None,4829 'default-tag',4830 ),4831 (4832 'aa-bb, cc-dd',4833 ['ee-ff', 'ee'],4834 'gg-hh', 'default-tag', None,4835 'default-tag',4836 ),4837 # If none of the ranges in the header match, the `default_range`4838 # argument is None or does not match, the `default_tag` argument is4839 # not None, and there is a '*' range in the header with q=0, then4840 # the `default_tag` argument is not acceptable.4841 (4842 'aa-bb, cc-dd, *;q=0',4843 ['ee-ff', 'ee'],4844 'gg-hh', 'ii-jj', 'default',4845 'default',4846 ),4847 # If none of the ranges in the header match, the `default_range`4848 # argument is None or does not match, the `default_tag` argument is4849 # not None and matches a non-'*' range in the header with q=04850 # exactly, then the `default_tag` argument is not acceptable.4851 (4852 'aa-bb, cc-dd, iI-jJ;q=0',4853 ['ee-ff', 'ee'],4854 'gg-hh', 'Ii-Jj', 'default',4855 'default',4856 ),4857 # If none of the ranges in the header match, the `default_range`4858 # argument is None or does not match, and the `default_tag`4859 # argument is None, then we proceed to the `default` argument.4860 (4861 'aa-bb, cc-dd',4862 ['ee-ff', 'ee'],4863 None, None, 'default',4864 'default',4865 ),4866 (4867 'aa-bb, cc-dd',4868 ['ee-ff', 'ee'],4869 'gg-hh', None, 'default',4870 'default',4871 ),4872 # If we fall back to the `default` argument, and it is not a4873 # callable, the argument itself is returned.4874 (4875 'aa',4876 ['bb'],4877 None, None, 0,4878 0,4879 ),4880 (4881 'Aa, cC;q=0',4882 ['bb'],4883 'aA-Cc', 'Cc', ['non-callable object'],4884 ['non-callable object'],4885 ),4886 # If we fall back to the `default` argument, and it is a callable,4887 # it is called, and the callable's return value is returned by the4888 # method.4889 (4890 'aa',4891 ['bb'],4892 None, None, lambda: 'callable called',4893 'callable called',4894 ),4895 (4896 'Aa, cc;q=0',4897 ['bb'],4898 'aA-cC', 'cc', lambda: 'callable called',4899 'callable called',4900 ),4901 # Even if the 'default' argument is a str that matches a q=0 range4902 # in the header, it is still returned.4903 (4904 'aa, *;q=0',4905 ['bb'],4906 None, None, 'cc',4907 'cc',4908 ),4909 (4910 'aa, cc;q=0',4911 ['bb'],4912 None, None, 'cc',4913 'cc',4914 ),4915 # If the `default_tag` argument is not acceptable because of a q=04916 # range in the header, and the `default` argument is None, then4917 # None is returned.4918 (4919 'aa, Bb;q=0',4920 ['cc'],4921 None, 'bB', None,4922 None,4923 ),4924 (4925 'aa, *;q=0',4926 ['cc'],4927 None, 'bb', None,4928 None,4929 ),4930 # Test that method works with empty `language_tags`:4931 (4932 'range',4933 [],4934 None, 'default-tag', None,4935 'default-tag',4936 ),4937 # Test that method works with empty `default_range`:4938 (4939 'range',4940 [],4941 '', 'default-tag', None,4942 'default-tag',4943 ),4944 (4945 'range',4946 ['tag'],4947 '', 'default-tag', None,4948 'default-tag',4949 ),4950 # Test that method works with empty `default_tag`:4951 (4952 'range',4953 [],4954 '', '', None,4955 '',4956 ),4957 (4958 'range',4959 ['tag'],4960 'default-range', '', None,4961 '',4962 ),4963 ]4964 )4965 def test_lookup(4966 self, header_value, language_tags, default_range, default_tag,4967 default, expected,4968 ):4969 instance = AcceptLanguageValidHeader(header_value=header_value)4970 returned = instance.lookup(4971 language_tags=language_tags,4972 default_range=default_range,4973 default_tag=default_tag,4974 default=default,4975 )4976 assert returned == expected4977 @pytest.mark.parametrize('header_value, offer, expected_returned', [4978 ('en-gb', 'en-gb', 1),4979 ('en-gb;q=0.5', 'en-gb', 0.5),4980 ('en-gb', 'sr-Cyrl', None),4981 ])4982 @pytest.mark.filterwarnings(IGNORE_QUALITY)4983 def test_quality(self, header_value, offer, expected_returned):4984 instance = AcceptLanguageValidHeader(header_value=header_value)4985 returned = instance.quality(offer=offer)4986 assert returned == expected_returned4987class TestAcceptLanguageNoHeader(object):4988 def test___init__(self):4989 instance = AcceptLanguageNoHeader()4990 assert instance.header_value is None4991 assert instance.parsed is None4992 assert instance._parsed_nonzero is None4993 assert isinstance(instance, AcceptLanguage)4994 def test___add___None(self):4995 instance = AcceptLanguageNoHeader()4996 result = instance + None4997 assert isinstance(result, AcceptLanguageNoHeader)4998 assert result is not instance4999 @pytest.mark.parametrize('right_operand', [5000 '',5001 [],5002 (),5003 {},5004 'en_gb',5005 ['en_gb'],5006 ('en_gb',),5007 {'en_gb': 1.0},5008 ])5009 def test___add___invalid_value(self, right_operand):5010 left_operand = AcceptLanguageNoHeader()5011 result = left_operand + right_operand5012 assert isinstance(result, AcceptLanguageNoHeader)5013 assert result is not left_operand5014 @pytest.mark.parametrize('str_', ['', 'en_gb'])5015 def test___add___other_type_with_invalid___str__(self, str_,):5016 left_operand = AcceptLanguageNoHeader()5017 class Other(object):5018 def __str__(self):5019 return str_5020 result = left_operand + Other()5021 assert isinstance(result, AcceptLanguageNoHeader)5022 assert result is not left_operand5023 @pytest.mark.parametrize('value, value_as_header', [5024 ('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),5025 ([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),5026 ((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),5027 ({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),5028 ])5029 def test___add___valid_value(self, value, value_as_header):5030 result = AcceptLanguageNoHeader() + value5031 assert isinstance(result, AcceptLanguageValidHeader)5032 assert result.header_value == value_as_header5033 def test___add___other_type_with_valid___str__(self):5034 class Other(object):5035 def __str__(self):5036 return 'en-gb;q=0.5, fr;q=0, es'5037 right_operand = Other()5038 result = AcceptLanguageNoHeader() + right_operand5039 assert isinstance(result, AcceptLanguageValidHeader)5040 assert result.header_value == str(right_operand)5041 def test___add___AcceptLanguageValidHeader(self):5042 right_operand = AcceptLanguageValidHeader(5043 header_value=', ,fr;q=0, \tes;q=1,',5044 )5045 result = AcceptLanguageNoHeader() + right_operand5046 assert isinstance(result, AcceptLanguageValidHeader)5047 assert result.header_value == right_operand.header_value5048 def test___add___AcceptLanguageNoHeader(self):5049 left_operand = AcceptLanguageNoHeader()5050 right_operand = AcceptLanguageNoHeader()5051 result = left_operand + right_operand5052 assert isinstance(result, AcceptLanguageNoHeader)5053 assert result is not left_operand5054 assert result is not right_operand5055 @pytest.mark.parametrize('invalid_header_value', ['', 'en_gb'])5056 def test___add___AcceptLanguageInvalidHeader(self, invalid_header_value):5057 left_operand = AcceptLanguageNoHeader()5058 result = left_operand + AcceptLanguageInvalidHeader(5059 header_value=invalid_header_value,5060 )5061 assert isinstance(result, AcceptLanguageNoHeader)5062 assert result is not left_operand5063 def test___bool__(self):5064 instance = AcceptLanguageNoHeader()5065 returned = bool(instance)5066 assert returned is False5067 @pytest.mark.filterwarnings(IGNORE_CONTAINS)5068 def test___contains__(self):5069 instance = AcceptLanguageNoHeader()5070 returned = ('any-tag' in instance)5071 assert returned is True5072 @pytest.mark.filterwarnings(IGNORE_ITER)5073 def test___iter__(self):5074 instance = AcceptLanguageNoHeader()5075 returned = list(instance)5076 assert returned == []5077 def test___radd___None(self):5078 right_operand = AcceptLanguageNoHeader()5079 result = None + right_operand5080 assert isinstance(result, AcceptLanguageNoHeader)5081 assert result is not right_operand5082 @pytest.mark.parametrize('left_operand', [5083 '',5084 [],5085 (),5086 {},5087 'en_gb',5088 ['en_gb'],5089 ('en_gb',),5090 {'en_gb': 1.0},5091 ])5092 def test___radd___invalid_value(self, left_operand):5093 right_operand = AcceptLanguageNoHeader()5094 result = left_operand + right_operand5095 assert isinstance(result, AcceptLanguageNoHeader)5096 assert result is not right_operand5097 @pytest.mark.parametrize('str_', ['', 'en_gb', ','])5098 def test___radd___other_type_with_invalid___str__(self, str_,):5099 right_operand = AcceptLanguageNoHeader()5100 class Other(object):5101 def __str__(self):5102 return str_5103 result = Other() + right_operand5104 assert isinstance(result, AcceptLanguageNoHeader)5105 assert result is not right_operand5106 @pytest.mark.parametrize('value, value_as_header', [5107 ('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),5108 ([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),5109 ((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),5110 ({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),5111 ])5112 def test___radd___valid_value(self, value, value_as_header):5113 result = value + AcceptLanguageNoHeader()5114 assert isinstance(result, AcceptLanguageValidHeader)5115 assert result.header_value == value_as_header5116 def test___radd___other_type_with_valid___str__(self):5117 class Other(object):5118 def __str__(self):5119 return 'en-gb;q=0.5, fr;q=0, es'5120 left_operand = Other()5121 result = left_operand + AcceptLanguageNoHeader()5122 assert isinstance(result, AcceptLanguageValidHeader)5123 assert result.header_value == str(left_operand)5124 def test___repr__(self):5125 instance = AcceptLanguageNoHeader()5126 assert repr(instance) == '<AcceptLanguageNoHeader>'5127 def test___str__(self):5128 instance = AcceptLanguageNoHeader()5129 assert str(instance) == '<no header in request>'5130 def test_basic_filtering(self):5131 instance = AcceptLanguageNoHeader()5132 returned = instance.basic_filtering(language_tags=['tag1', 'tag2'])5133 assert returned == []5134 @pytest.mark.parametrize('offers, default_match, expected_returned', [5135 (['foo', 'bar'], None, 'foo'),5136 ([('foo', 1), ('bar', 0.5)], None, 'foo'),5137 ([('foo', 0.5), ('bar', 1)], None, 'bar'),5138 ([('foo', 0.5), 'bar'], None, 'bar'),5139 ([('foo', 0.5), 'bar'], object(), 'bar'),5140 ([], 'fallback', 'fallback'),5141 ])5142 @pytest.mark.filterwarnings(IGNORE_BEST_MATCH)5143 def test_best_match(self, offers, default_match, expected_returned):5144 instance = AcceptLanguageNoHeader()5145 returned = instance.best_match(5146 offers=offers, default_match=default_match,5147 )5148 assert returned == expected_returned5149 def test_lookup_default_tag_and_default_cannot_both_be_None(self):5150 instance = AcceptLanguageNoHeader()5151 with pytest.raises(TypeError):5152 instance.lookup(default_tag=None, default=None)5153 @pytest.mark.parametrize('default_tag, default, expected', [5154 # If `default_tag` is not None, it is returned.5155 ('default-tag', 'default', 'default-tag'),5156 # If `default_tag` is None, we proceed to the `default` argument. If5157 # `default` is not a callable, the argument itself is returned.5158 (None, 0, 0),5159 # If `default` is a callable, it is called, and the callable's return5160 # value is returned by the method.5161 (None, lambda: 'callable called', 'callable called'),5162 ])5163 def test_lookup(self, default_tag, default, expected):5164 instance = AcceptLanguageNoHeader()5165 returned = instance.lookup(5166 default_tag=default_tag,5167 default=default,5168 )5169 assert returned == expected5170 @pytest.mark.filterwarnings(IGNORE_QUALITY)5171 def test_quality(self):5172 instance = AcceptLanguageNoHeader()5173 returned = instance.quality(offer='any-tag')5174 assert returned == 1.05175class TestAcceptLanguageInvalidHeader(object):5176 def test___init__(self):5177 header_value = 'invalid header'5178 instance = AcceptLanguageInvalidHeader(header_value=header_value)5179 assert instance.header_value == header_value5180 assert instance.parsed is None5181 assert instance._parsed_nonzero is None5182 assert isinstance(instance, AcceptLanguage)5183 def test___add___None(self):5184 instance = AcceptLanguageInvalidHeader(header_value='')5185 result = instance + None5186 assert isinstance(result, AcceptLanguageNoHeader)5187 @pytest.mark.parametrize('right_operand', [5188 '',5189 [],5190 (),5191 {},5192 'en_gb',5193 ['en_gb'],5194 ('en_gb',),5195 {'en_gb': 1.0},5196 ])5197 def test___add___invalid_value(self, right_operand):5198 result = AcceptLanguageInvalidHeader(header_value='') + right_operand5199 assert isinstance(result, AcceptLanguageNoHeader)5200 @pytest.mark.parametrize('str_', ['', 'en_gb'])5201 def test___add___other_type_with_invalid___str__(self, str_):5202 class Other(object):5203 def __str__(self):5204 return str_5205 result = AcceptLanguageInvalidHeader(header_value='') + Other()5206 assert isinstance(result, AcceptLanguageNoHeader)5207 @pytest.mark.parametrize('value', [5208 'en',5209 ['en'],5210 ('en',),5211 {'en': 1.0},5212 ])5213 def test___add___valid_header_value(self, value):5214 result = AcceptLanguageInvalidHeader(header_value='') + value5215 assert isinstance(result, AcceptLanguageValidHeader)5216 assert result.header_value == 'en'5217 def test___add___other_type_valid_header_value(self):5218 class Other(object):5219 def __str__(self):5220 return 'en'5221 result = AcceptLanguageInvalidHeader(header_value='') + Other()5222 assert isinstance(result, AcceptLanguageValidHeader)5223 assert result.header_value == 'en'5224 def test___add___AcceptLanguageValidHeader(self):5225 right_operand = AcceptLanguageValidHeader(header_value='en')5226 result = AcceptLanguageInvalidHeader(header_value='') + right_operand5227 assert isinstance(result, AcceptLanguageValidHeader)5228 assert result.header_value == right_operand.header_value5229 assert result is not right_operand5230 def test___add___AcceptLanguageNoHeader(self):5231 right_operand = AcceptLanguageNoHeader()5232 result = AcceptLanguageInvalidHeader(header_value='') + right_operand5233 assert isinstance(result, AcceptLanguageNoHeader)5234 assert result is not right_operand5235 def test___add___AcceptLanguageInvalidHeader(self):5236 result = AcceptLanguageInvalidHeader(header_value='') + \5237 AcceptLanguageInvalidHeader(header_value='')5238 assert isinstance(result, AcceptLanguageNoHeader)5239 def test___bool__(self):5240 instance = AcceptLanguageInvalidHeader(header_value='')5241 returned = bool(instance)5242 assert returned is False5243 @pytest.mark.filterwarnings(IGNORE_CONTAINS)5244 def test___contains__(self):5245 instance = AcceptLanguageInvalidHeader(header_value='')5246 returned = ('any-tag' in instance)5247 assert returned is True5248 @pytest.mark.filterwarnings(IGNORE_ITER)5249 def test___iter__(self):5250 instance = AcceptLanguageInvalidHeader(header_value='')5251 returned = list(instance)5252 assert returned == []5253 def test___radd___None(self):5254 instance = AcceptLanguageInvalidHeader(header_value='')5255 result = None + instance5256 assert isinstance(result, AcceptLanguageNoHeader)5257 @pytest.mark.parametrize('left_operand', [5258 '',5259 [],5260 (),5261 {},5262 'en_gb',5263 ['en_gb'],5264 ('en_gb',),5265 {'en_gb': 1.0},5266 ])5267 def test___radd___invalid_value(self, left_operand):5268 result = left_operand + AcceptLanguageInvalidHeader(header_value='')5269 assert isinstance(result, AcceptLanguageNoHeader)5270 @pytest.mark.parametrize('str_', ['', 'en_gb'])5271 def test___radd___other_type_with_invalid___str__(self, str_):5272 class Other(object):5273 def __str__(self):5274 return str_5275 result = Other() + AcceptLanguageInvalidHeader(header_value='')5276 assert isinstance(result, AcceptLanguageNoHeader)5277 @pytest.mark.parametrize('value', [5278 'en',5279 ['en'],5280 ('en',),5281 {'en': 1.0},5282 ])5283 def test___radd___valid_header_value(self, value):5284 result = value + AcceptLanguageInvalidHeader(header_value='')5285 assert isinstance(result, AcceptLanguageValidHeader)5286 assert result.header_value == 'en'5287 def test___radd___other_type_valid_header_value(self):5288 class Other(object):5289 def __str__(self):5290 return 'en'5291 result = Other() + AcceptLanguageInvalidHeader(header_value='')5292 assert isinstance(result, AcceptLanguageValidHeader)5293 assert result.header_value == 'en'5294 def test___repr__(self):5295 instance = AcceptLanguageInvalidHeader(header_value='\x00')5296 assert repr(instance) == '<AcceptLanguageInvalidHeader>'5297 def test___str__(self):5298 instance = AcceptLanguageInvalidHeader(header_value="invalid header")5299 assert str(instance) == '<invalid header value>'5300 def test_basic_filtering(self):5301 instance = AcceptLanguageInvalidHeader(header_value='')...

Full Screen

Full Screen

get_constant_data.py

Source:get_constant_data.py Github

copy

Full Screen

1import urllib.request2import urllib.parse3from bs4 import BeautifulSoup, Comment4import json5import logging6from logging.handlers import TimedRotatingFileHandler7import sys8import time9import math10import socket11import re12import getopt13import datetime14import threading15import lxml16import cchardet17import ssl18league_totals_url = "https://www.hockey-reference.com/{}/NHL_{}_{}.html"19current_year_stats_url = "https://www.hockey-reference.com/{}/NHL_{}.html"20max_request_retries = 321retry_failure_delay = 322request_headers = {23 "User-Agent" : "NHLCompareRedditBot"24}25logname = "nhl-constants.log"26logger = logging.getLogger("nhl-constants")27logger.setLevel(logging.INFO)28formatter = logging.Formatter(fmt='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')29handler = TimedRotatingFileHandler(logname, when="midnight", interval=1)30handler.suffix = "%Y%m%d"31handler.setFormatter(formatter)32logger.addHandler(handler)33streamhandler = logging.StreamHandler(sys.stdout)34streamhandler.setLevel(logging.DEBUG)35logger.addHandler(streamhandler)36start_year = 191737end_year = 202138current_year_playoffs_started = False39year_games_played = [40 {41 "start_year" : start_year,42 "end_year" : 1924,43 "roster" : 944 },45 {46 "start_year" : 1925,47 "end_year" : 1928,48 "roster" : 1249 },50 {51 "start_year" : 1929,52 "end_year" : 1931,53 "roster" : 1554 },55 {56 "start_year" : 1932,57 "end_year" : 1937,58 "roster" : 1459 },60 {61 "start_year" : 1938,62 "end_year" : 1941,63 "roster" : 1564 },65 {66 "start_year" : 1942,67 "end_year" : 1948,68 "roster" : 1469 },70 {71 "start_year" : 1949,72 "end_year" : 1950,73 "roster" : 1774 },75 {76 "start_year" : 1951,77 "end_year" : 1951,78 "roster" : 1579 },80 {81 "start_year" : 1952,82 "end_year" : 1952,83 "roster" : 15.584 },85 {86 "start_year" : 1953,87 "end_year" : 1953,88 "roster" : 1689 },90 {91 "start_year" : 1954,92 "end_year" : 1959,93 "roster" : 1794 },95 {96 "start_year" : 1960,97 "end_year" : 1970,98 "roster" : 1699 },100 {101 "start_year" : 1971,102 "end_year" : 1981,103 "roster" : 17104 },105 {106 "start_year" : 1982,107 "end_year" : end_year,108 "roster" : 18109 }110]111ssl._create_default_https_context = ssl._create_unverified_context112def main():113 year_short = "y"114 year_long = "year"115 try:116 options = getopt.getopt(sys.argv[1:], year_short + ":", [year_long + "="])[0]117 except getopt.GetoptError as err:118 logger.error("Encountered error \"" + str(err) + "\" parsing arguments")119 return120 year = None121 for opt, arg in options:122 if opt in ("-" + year_short, "--" + year_long):123 year = int(arg.strip())124 totals = None125 if year:126 with open("yearly_totals.json", "r") as file:127 totals = json.load(file)128 get_totals(year, totals)129 else:130 totals = get_totals(None, None)131 with open("yearly_totals.json", "w") as file:132 file.write(json.dumps(totals, indent=4, sort_keys=True))133def get_totals(specific_year, totals):134 logger.info("Getting league total data for year " + str(specific_year))135 format_strs = {136 "Skater" : "skaters",137 "Goalie" : "goalies"138 }139 if not totals:140 totals = {141 "Standard" : {142 "Skater" : {143 "F" : {},144 "D" : {}145 },146 "Goalie" : {147 "G" : {}148 },149 "TOT" : {}150 },151 "Playoffs" : {152 "Skater" : {153 "F" : {},154 "D" : {}155 },156 "Goalie" : {157 "G" : {}158 },159 "TOT" : {}160 }161 }162 elif specific_year:163 for over_key in totals:164 for key in totals[over_key]:165 if key == "TOT":166 totals[over_key][key][str(specific_year)] = {}167 else:168 for pos in totals[over_key][key]:169 totals[over_key][key][pos][str(specific_year)] = {}170 headers_to_read = {171 "Skater" : {172 "GP",173 "G",174 "A",175 "PTS",176 "+/-",177 "PIM",178 "PPG",179 "SHG",180 "PPA",181 "S",182 "TOI"183 },184 "Goalie" : {185 "GP",186 "W",187 "L",188 "T/O",189 "GA",190 "SA",191 "SV",192 "SO",193 "TOI",194 "G",195 "A",196 "PTS",197 "PIM"198 }199 }200 years = None201 if specific_year:202 years = [specific_year]203 else:204 years = range(start_year, end_year + 1)205 team_map_by_year = {}206 for over_key in totals:207 logger.info("Getting league total game data for " + over_key)208 current_percent = 10209 count = 0210 for year in years:211 if over_key == "Playoffs" and year == end_year and not current_year_playoffs_started:212 logger.info("Skipping current year " + str(year) + " as playoffs have not stared yet")213 continue214 team_map_by_year_val = calculate_year_games_by_team(year, over_key == "Playoffs")215 if not over_key in team_map_by_year:216 team_map_by_year[over_key] = {}217 team_map_by_year[over_key][str(year)] = team_map_by_year_val218 219 count += 1220 percent_complete = 100 * (count / len(years))221 if not specific_year and count != 1 and percent_complete >= current_percent:222 logger.info(str(current_percent) + "%")223 current_percent += 10224 for over_key in totals:225 for key in totals[over_key]:226 if key == "TOT":227 continue228 229 logger.info("Getting league total data for " + over_key + " : " + key)230 current_percent = 10231 count = 0232 for year in years:233 if over_key == "Playoffs" and year == end_year and not current_year_playoffs_started:234 logger.info("Skipping current year " + str(year) + " as playoffs have not stared yet")235 continue236 request = urllib.request.Request(league_totals_url.format("playoffs" if over_key == "Playoffs" else "leagues", year + 1, format_strs[key]), headers=request_headers)237 try:238 response, player_page = url_request(request)239 except urllib.error.HTTPError as err:240 if err.status == 404:241 continue242 else:243 raise244 245 table = player_page.find("table", id="stats")246 if not table:247 continue248 if key == "Goalie":249 if not str(year) in totals[over_key][key]["G"]:250 totals[over_key][key]["G"][str(year)] = {}251 else:252 if not str(year) in totals[over_key][key]["F"]:253 totals[over_key][key]["F"][str(year)] = {}254 totals[over_key][key]["D"][str(year)] = {}255 header_columns = table.find("thead").find("tr", {"class" : "over_header"}).find_next_sibling().find_all("th")256 header_values = []257 for header in header_columns:258 header_values.append(header.find(text=True).strip())259 standard_table_rows = table.find("tbody").find_all("tr")260 for row in standard_table_rows:261 classes = row.get("class")262 if not classes or not "thead" in classes:263 team = row.find("td", {"data-stat" : "team_id"}).find(text=True)264 if key == "Goalie":265 pos = "G"266 else:267 pos = row.find("td", {"data-stat" : "pos"}).find(text=True)268 pos = "D" if pos == "D" else "F"269 if team == "TOT":270 continue271 columns = row.find_all("td", recursive=False)272 for sub_index, column in enumerate(columns):273 real_index = sub_index + 1274 header_value = header_values[real_index]275 if header_value == "TOI":276 continue277 elif header_value == "ATOI" or header_value == "MIN":278 header_value = "TOI"279 elif header_value == "PP":280 if column["data-stat"] == "goals_pp":281 header_value = "PPG"282 else:283 header_value = "PPA"284 elif header_value == "SH":285 if column["data-stat"] == "goals_sh":286 header_value = "SHG"287 if header_value in headers_to_read[key]:288 column_contents = column.find(text=True)289 column_value = 0.0290 if column_contents:291 if header_value == "TOI":292 if column_contents.isdigit():293 column_value = int(column_contents) * 60294 else:295 time_split = column_contents.split(":")296 minutes = int(time_split[0])297 seconds = int(time_split[1])298 column_value = (minutes * 60) + seconds299 column_value *= int(row.find("td", {"data-stat" : "games_played"}).find(text=True))300 else:301 column_value = float(column_contents)302 if not team in totals[over_key][key][pos][str(year)]:303 totals[over_key][key][pos][str(year)][team] = {}304 if not header_value in totals[over_key][key][pos][str(year)][team]:305 totals[over_key][key][pos][str(year)][team][header_value] = 0.0306 totals[over_key][key][pos][str(year)][team][header_value] += column_value307 308 if not str(year) in totals[over_key]["TOT"]:309 totals[over_key]["TOT"][str(year)] = {}310 if key == "Skater":311 for pos in ["F", "D"]:312 for team in totals[over_key][key][pos][str(year)]:313 if not team in totals[over_key]["TOT"][str(year)]:314 totals[over_key]["TOT"][str(year)][team] = {}315 for header_value in totals[over_key][key][pos][str(year)][team]:316 if not header_value in totals[over_key]["TOT"][str(year)][team]:317 totals[over_key]["TOT"][str(year)][team][header_value] = 0.0318 totals[over_key]["TOT"][str(year)][team][header_value] += totals[over_key][key][pos][str(year)][team][header_value]319 else:320 for team in totals[over_key][key]["G"][str(year)]:321 if not team in totals[over_key]["TOT"][str(year)]:322 totals[over_key]["TOT"][str(year)][team] = {}323 for header_value in totals[over_key][key]["G"][str(year)][team]:324 if not header_value in totals[over_key]["TOT"][str(year)][team]:325 totals[over_key]["TOT"][str(year)][team][header_value] = 0.0326 totals[over_key]["TOT"][str(year)][team][header_value] += totals[over_key][key]["G"][str(year)][team][header_value]327 328 count += 1329 percent_complete = 100 * (count / len(years))330 if not specific_year and count != 1 and percent_complete >= current_percent:331 logger.info(str(current_percent) + "%")332 current_percent += 10333 for over_key in totals:334 for key in totals[over_key]:335 logger.info("Combining league total data for " + over_key + " : " + key)336 if key == "TOT":337 for year in years:338 if str(year) in totals[over_key][key]:339 totals[over_key][key][str(year)]["NHL"] = {}340 for team in totals[over_key][key][str(year)]:341 if team != "NHL":342 for header_value in team_map_by_year[over_key][str(year)][team]:343 totals[over_key][key][str(year)][team][header_value] = team_map_by_year[over_key][str(year)][team][header_value]344 for header_value in totals[over_key][key][str(year)][team]:345 if header_value not in totals[over_key][key][str(year)]["NHL"]:346 totals[over_key][key][str(year)]["NHL"][header_value] = 0.0347 totals[over_key][key][str(year)]["NHL"][header_value] += totals[over_key][key][str(year)][team][header_value]348 for year_game_played in year_games_played:349 year_start_year = year_game_played["start_year"]350 year_end_year = year_game_played["end_year"]351 if (not year_start_year or year >= year_start_year) and (not year_end_year or year <= year_end_year):352 roster_per_season = year_game_played["roster"]353 354 totals[over_key][key][str(year)]["NHL"]["roster_size"] = roster_per_season355 else:356 for pos in totals[over_key][key]:357 for year in years:358 if str(year) in totals[over_key][key][pos]:359 totals[over_key][key][pos][str(year)]["NHL"] = {}360 for team in totals[over_key][key][pos][str(year)]:361 if team != "NHL":362 if key == "Skater":363 for header_value in team_map_by_year[over_key][str(year)][team]:364 totals[over_key][key][pos][str(year)][team][header_value] = team_map_by_year[over_key][str(year)][team][header_value]365 for header_value in totals[over_key][key][pos][str(year)][team]:366 if header_value not in totals[over_key][key][pos][str(year)]["NHL"]:367 totals[over_key][key][pos][str(year)]["NHL"][header_value] = 0.0368 totals[over_key][key][pos][str(year)]["NHL"][header_value] += totals[over_key][key][pos][str(year)][team][header_value]369 return totals370def calculate_year_games_by_team(year, for_playoffs):371 teams = {}372 request = urllib.request.Request(current_year_stats_url.format("playoffs" if for_playoffs else "leagues", year + 1), headers=request_headers)373 try:374 response, player_page = url_request(request)375 except urllib.error.HTTPError as err:376 if err.status == 404:377 return None378 else:379 raise380 table_name = "^teams$" if for_playoffs else "^stats"381 team_abbr_map = {}382 if for_playoffs:383 original_player_page = player_page384 request = urllib.request.Request(current_year_stats_url.format("leagues", year + 1), headers=request_headers)385 try:386 response, player_page = url_request(request)387 except urllib.error.HTTPError as err:388 if err.status == 404:389 return None390 else:391 raise392 table = player_page.find("table", id="stats")393 if not table:394 comments = player_page.find_all(string=lambda text: isinstance(text, Comment))395 for c in comments:396 temp_soup = BeautifulSoup(c, "lxml")397 temp_table = temp_soup.find("table", id="stats")398 if temp_table:399 table = temp_table400 break401 if table:402 standard_table_rows = table.find("tbody").find_all("tr")403 for row in standard_table_rows:404 classes = row.get("class")405 if not classes or not "thead" in classes:406 team_row = row.find("td", {"data-stat" : "team_name"})407 team_link = row.find("td", {"data-stat" : "team_name"}).find("a")408 if not team_link:409 continue410 team_name = team_row.find(text=True)411 team_abbr = team_link["href"].split("/")[2].upper()412 if not team_abbr in team_abbr_map:413 team_abbr_map[team_name] = team_abbr414 415 player_page = original_player_page416 tables = player_page.findAll("table", id=re.compile(table_name))417 if not tables:418 comments = player_page.find_all(string=lambda text: isinstance(text, Comment))419 for c in comments:420 temp_soup = BeautifulSoup(c, "lxml")421 temp_tables = temp_soup.findAll("table", id=re.compile(table_name))422 if temp_tables:423 tables = temp_tables424 break425 for table in tables:426 standard_table_rows = table.find("tbody").find_all("tr")427 header_columns = table.find("thead").find_all("th")428 429 header_values = []430 for header in header_columns:431 header_text = header.find(text=True)432 if header_text:433 header_values.append(header_text.strip())434 else:435 header_values.append(None)436 standard_table_rows = table.find("tbody").find_all("tr")437 for row in standard_table_rows:438 classes = row.get("class")439 if not classes or not "thead" in classes:440 if for_playoffs:441 team_name = row.find("td", {"data-stat" : "team_name"}).find(text=True)442 if team_name == "League Average":443 continue444 team_abbr = team_abbr_map[team_name]445 else:446 team_link = row.find("td", {"data-stat" : "team_name"}).find("a")447 if not team_link:448 continue449 team_abbr = team_link["href"].split("/")[2].upper()450 columns = row.find_all("td", recursive=False)451 for column in columns:452 if hasattr(column, "data-stat"):453 if column["data-stat"] == "games":454 header_value = "T-GP"455 elif column["data-stat"] == "goals":456 header_value = "T-GF"457 elif column["data-stat"] == "goals_against" or column["data-stat"] == "opp_goals":458 header_value = "T-GA"459 elif column["data-stat"] == "points":460 header_value = "T-PTS"461 else:462 continue463 column_contents = column.find(text=True)464 column_value = 0465 if column_contents:466 column_value = int(column_contents)467 468 if not team_abbr in teams:469 teams[team_abbr] = {}470 if not header_value in teams[team_abbr]:471 teams[team_abbr][header_value] = 0.0472 if header_value == "T-GF":473 wins_shootout = row.find("td", {"data-stat" : "wins_shootout"})474 if wins_shootout:475 wins_shootout_str = wins_shootout.find(text=True)476 if wins_shootout_str and wins_shootout_str.isdigit():477 column_value += int(wins_shootout_str)478 elif header_value == "T-GA":479 losses_shootout = row.find("td", {"data-stat" : "losses_shootout"})480 if losses_shootout:481 losses_shootout_str = losses_shootout.find(text=True)482 if losses_shootout_str and losses_shootout_str.isdigit():483 column_value += int(losses_shootout_str)484 485 teams[team_abbr][header_value] = column_value486 return teams487def url_request(request, timeout=30):488 failed_counter = 0489 while(True):490 try:491 response = urllib.request.urlopen(request, timeout=timeout)492 text = response.read()493 try:494 text = text.decode(response.headers.get_content_charset())495 except UnicodeDecodeError:496 return response, BeautifulSoup(text, "html.parser")497 return response, BeautifulSoup(text, "lxml")498 except Exception:499 failed_counter += 1500 if failed_counter > max_request_retries:501 raise502 delay_step = 10503 logger.info("#" + str(threading.get_ident()) + "# " + "Retrying in " + str(retry_failure_delay) + " seconds to allow request to " + request.get_full_url() + " to chill")504 time_to_wait = int(math.ceil(float(retry_failure_delay)/float(delay_step)))505 for i in range(retry_failure_delay, 0, -time_to_wait):506 logger.info("#" + str(threading.get_ident()) + "# " + str(i))507 time.sleep(time_to_wait)508 logger.info("#" + str(threading.get_ident()) + "# " + "0")509if __name__ == "__main__":...

Full Screen

Full Screen

derived.py

Source:derived.py Github

copy

Full Screen

1# STD-lib2# 3rd-party3import numpy as np4# Local5from pyigra2.base import IGRABase6class Derived(IGRABase):7 def __init__(self, filename):8 # Init parent class9 super().__init__(filename)10 # Set file specific headers and parameters11 # OBS! These index values are exactly what was given in "igra2-derived-format.txt". However, python start index12 # with zero. This is taken care of in parent class IGRABase._set_header() and IGRABase._set_parameters.13 # Header name and index14 self._header_name_index = {15 "HEADREC": [1, 1],16 "ID": [2, 12],17 "YEAR": [14, 17],18 "MONTH": [19, 20],19 "DAY": [22, 23],20 "HOUR": [25, 26],21 "RELTIME": [28, 31],22 "NUMLEV": [32, 36],23 "PW": [38, 43],24 "INVPRESS": [44, 49],25 "INVHGT": [50, 55],26 "INVTEMPDIF": [56, 61],27 "MIXPRESS": [62, 67],28 "MIXHGT": [68, 73],29 "FRZPRESS": [74, 79],30 "FRZHGT": [80, 85],31 "LCLPRESS": [86, 91],32 "LCLHGT": [92, 97],33 "LFCPRESS": [98, 103],34 "LFCHGT": [104, 109],35 "LNBPRESS": [110, 115],36 "LNBHGT": [116, 121],37 "LI": [122, 127],38 "SI": [128, 133],39 "KI": [134, 139],40 "TTI": [140, 145],41 "CAPE": [146, 151],42 "CIN": [152, 157],43 }44 # Header units:45 # Structure: header_name: [raw_unit, converted_unit]46 self._header_units = {47 "HEADREC": ["-", "-"],48 "ID": ["-", "-"],49 "YEAR": ["yyyy", "yyyy"],50 "MONTH": ["mm", "mm"],51 "DAY": ["dd", "dd"],52 "HOUR": ["HH", "HH"],53 "RELTIME": ["HHMM", "HHMM"],54 "NUMLEV": ["-", "-"],55 "PW": ["mm*100", "mm"],56 "INVPRESS": ["Pa", "Pa"],57 "INVHGT": ["m", "m"],58 "INVTEMPDIF": ["K*10", "K"],59 "MIXPRESS": ["Pa", "Pa"],60 "MIXHGT": ["m", "m"],61 "FRZPRESS": ["Pa", "Pa"],62 "FRZHGT": ["m", "m"],63 "LCLPRESS": ["Pa", "Pa"],64 "LCLHGT": ["m", "m"],65 "LFCPRESS": ["Pa", "Pa"],66 "LFCHGT": ["m", "m"],67 "LNBPRESS": ["Pa", "Pa"],68 "LNBHGT": ["m", "m"],69 "LI": ["deg C", "K"],70 "SI": ["deg C", "K"],71 "KI": ["deg C", "K"],72 "TTI": ["deg C", "K"],73 "CAPE": ["J/kg", "J/kg"],74 "CIN": ["J/kg", "J/kg"],75 }76 # Parameter name and index77 self._parameters_name_index = {78 "PRESS": [1, 7],79 "REPGPH": [9, 15],80 "CALCGPH": [17, 23],81 "TEMP": [25, 31],82 "TEMPGRAD": [33, 39],83 "PTEMP": [41, 47],84 "PTEMPGRAD": [49, 55],85 "VTEMP": [57, 63],86 "VPTEMP": [65, 71],87 "VAPPRESS": [73, 79],88 "SATVAP": [81, 87],89 "REPRH": [89, 95],90 "CALCRH": [97, 103],91 "RHGRAD": [105, 111],92 "UWND": [113, 119],93 "UWDGRAD": [121, 127],94 "VWND": [129, 135],95 "VWNDGRAD": [137, 143],96 "N": [145, 151],97 }98 # Parameter units:99 # Structure: parameter_name: [raw unit, converted unit]100 self._parameter_units = {101 "PRESS": ["Pa", "Pa"],102 "REPGPH": ["m", "m"],103 "CALCGPH": ["m", "m"],104 "TEMP": ["K * 10", "K"],105 "TEMPGRAD": ["(K/km) * 10", "K/m"],106 "PTEMP": ["K * 10", "K"],107 "PTEMPGRAD": ["(K/km) * 10", "K/m"],108 "VTEMP": ["K * 10", "K"],109 "VPTEMP": ["K * 10", "K"],110 "VAPPRESS": ["mb * 1000", "Pa"],111 "SATVAP": ["mb * 1000", "Pa"],112 "REPRH": ["% * 10", "%"],113 "CALCRH": ["% * 10", "%"],114 "RHGRAD": ["(%/km) * 10", "%/m"],115 "UWND": ["(m/s) * 10", "m/s"],116 "UWDGRAD": ["(m/s per km) * 10", "(m/s) / m"],117 "VWND": ["(m/s) * 10", "m/s"],118 "VWNDGRAD": ["(m/s per km) * 10", "(m/s) / m"],119 "N": ["-", "-"],120 }121 def _convert_header(self, header, date, hour):122 """Convert header123 :param header: header to convert124 :param date, date to update125 :param hour: hour to update126 :return: None127 """128 # Create target dict129 self.converted_data[date][hour]["header"] = {}130 # Remove whitespaces:131 for header_name, header_value in header.items():132 # Remove white space133 header_value = header_value.replace(" ", "")134 # These variables have the following definitions:135 # HEADREC is the header record indicator (always set to "#").136 # ID is the station identification code. See "igra2-stations.txt"137 # for a complete list of stations and their names and locations.138 # YEAR is the year of the sounding.139 # MONTH is the month of the sounding.140 # DAY is the day of the sounding.141 # HOUR is the hour of the sounding (99 = missing).142 # RELTIME is the release time of the sounding (format HHMM, missing=9999).143 # NUMLEV is the number of levels in the sounding (i.e., the number of144 # data records that follow).145 if header_name == "NUMLEV":146 header_value = IGRABase._missing_test("-99999", header_value)147 # New unit: -148 # PW is the precipitable water (mm*100) between the surface and 500 hPa.149 if header_name == "PW":150 header_value = IGRABase._missing_test("-99999", header_value)151 header_value = header_value / 100.0152 # New unit: mm153 # INVPRESS is the pressure (in Pa or mb*100) at the level of the154 # warmest temperature in the sounding. Only provided if155 # the warmest temperature is above the surface.156 if header_name == "INVPRESS":157 header_value = IGRABase._missing_test("-99999", header_value)158 # New unit: Pa159 # INVHGT is the height (in meters above the surface) of the warmest160 # temperature in the sounding. Only provided when the161 # warmest temperature is above the surface.162 if header_name == "INVHGT":163 header_value = IGRABase._missing_test("-99999", header_value)164 # New unit: m165 # INVTEMPDIF is the difference between the warmest temperature in the166 # sounding and the surface temperature (K * 10). Only provided if167 # the warmest temperature is above the surface.168 if header_name == "INVTEMPDIF":169 header_value = IGRABase._missing_test("-99999", header_value)170 header_value = header_value / 10.0171 # New unit: K172 # MIXPRESS is the pressure (in Pa or mb * 100) at the top of the173 # mixed layer as determined using the parcel method.174 if header_name == "MIXPRESS":175 header_value = IGRABase._missing_test("-99999", header_value)176 # New unit: Pa177 # MIXHGT is the height (in meters above the surface) of the top of the178 # mixed layer As determined using the parcel method.179 if header_name == "MIXHGT":180 header_value = IGRABase._missing_test("-99999", header_value)181 # New unit: m182 # FRZPRESS is the pressure (in Pa or mb * 100) where the temperature183 # first reaches the freezing point when moving upward from184 # the surface. Determined by interpolating linearly with respect185 # to the logarithm of pressure between adjacent reported levels.186 # Not provided if the surface temperature is below freezing.187 if header_name == "FRZPRESS":188 header_value = IGRABase._missing_test("-99999", header_value)189 # New unit: Pa190 # FRZHGT is the height (in meters above the surface) where the temperature191 # first reaches the freezing point when moving upward from the192 # surface. Determined analogously to FRZPRESS. Not provided if the193 # surface temperature is below freezing.194 if header_name == "FRZHGT":195 header_value = IGRABase._missing_test("-99999", header_value)196 # New unit: m197 # LCLPRESS is the pressure (in Pa or mb * 100) of the lifting condensation198 # level.199 if header_name == "LCLPRESS":200 header_value = IGRABase._missing_test("-99999", header_value)201 # New unit: Pa202 # LCLHGT is the height (in meters above the surface) of the lifting203 # condensation level.204 if header_name == "LCLHGT":205 header_value = IGRABase._missing_test("-99999", header_value)206 # New unit: m207 # LFCPRESS is the pressure (in Pa or mb * 100) of the level of free convection.208 if header_name == "LFCPRESS":209 header_value = IGRABase._missing_test("-99999", header_value)210 # New unit: Pa211 # LFCHGT is the height (in meters above the surface) of the level of free212 # convection.213 if header_name == "LFCHGT":214 header_value = IGRABase._missing_test("-99999", header_value)215 # New unit: m216 # LNBPRESS is the pressure (in Pa or mb * 100) of the level of217 # neutral buoyancy (or equilibrium level).218 if header_name == "LNBPRESS":219 header_value = IGRABase._missing_test("-99999", header_value)220 # New unit: Pa221 # LNBHGT is the height (in meters above the surface) of the level of222 # neutral buoyancy (or equilibrium level).223 if header_name == "LNBHGT":224 header_value = IGRABase._missing_test("-99999", header_value)225 # New unit: m226 # LI is the lifted index (in degrees C).227 if header_name == "LI":228 header_value = IGRABase._missing_test("-99999", header_value)229 header_value = header_value + 273.15230 # New unit: K231 # SI is the Showalter index (in degrees C).232 if header_name == "SI":233 header_value = IGRABase._missing_test("-99999", header_value)234 header_value = header_value + 273.15235 # New unit: K236 # KI is the K index (in degrees C).237 if header_name == "KI":238 header_value = IGRABase._missing_test("-99999", header_value)239 header_value = header_value + 273.15240 # New unit: K241 # TTI is the total totals index (in degrees C).242 if header_name == "TTI":243 header_value = IGRABase._missing_test("-99999", header_value)244 header_value = header_value + 273.15245 # New unit: K246 # CAPE is the convective available potential energy (in J/kg).247 if header_name == "CAPE":248 header_value = IGRABase._missing_test("-99999", header_value)249 # New unit: J/kg250 # CIN is the convective inhibition (in J/kg).251 if header_name == "CIN":252 header_value = IGRABase._missing_test("-99999", header_value)253 # New unit: J/kg254 # Add to new header255 self.converted_data[date][hour]["header"][header_name] = header_value256 def _convert_parameters(self, parameters, date, hour):257 """Convert data258 :param parameters: parameters to convert259 :param date, date to update260 :param hour: hour to update261 :return: None262 """263 # Create target dict264 self.converted_data[date][hour]["parameters"] = {}265 for param_name, value_lst in parameters.items():266 # For every parameter do:267 # Convert to numpy array with dtype str268 array = np.array(value_lst, dtype=np.str)269 # Remove white spaces270 array = np.char.replace(array, " ", "")271 # Convert to float due to nans272 array = array.astype(np.float)273 # Missing values: -99999274 array[array == -99999] = np.nan275 # Convert specific parameters:276 # PRESS is the reported pressure (Pa or mb * 100).277 # REPGPH is the reported geopotential height (meters). This value is278 # often not available at significant levels.279 # CALCGPH is the calculated geopotential height (meters). The geopotential280 # height has been estimated by applying the hydrostatic balance to281 # the atmospheric layer between the next lower level with a282 # reported geopotential height and the current level.283 # TEMP is the reported temperature (K * 10).284 if param_name == "TEMP":285 array = array / 10.0286 # New unit: K287 # TEMPGRAD is the temperature gradient between the current level and288 # the next higher level with a temperature [(K/km) * 10, positive289 # if temperature increases with height].290 if param_name == "TEMPGRAD":291 array = array / 10000.0292 # New unit: K/m293 # PTEMP is the potential temperature (K * 10).294 if param_name == "PTEMP":295 array = array / 10.0296 # New unit: K297 # PTEMPGRAD is the potential temperature gradient between the current level298 # and the next higher level with a potential temperature299 # [(K/km) * 10, positive if potential temperature increases300 # with height].301 if param_name == "PTEMPGRAD":302 array = array / 10000.0303 # New unit: K/m304 # VTEMP is the virtual temperature (K * 10).305 if param_name == "VTEMP":306 array = array / 10.0307 # New unit: K308 # VPTEMP is the virtual potential temperature (K * 10).309 if param_name == "VPTEMP":310 array = array / 10.0311 # New unit: K312 # VAPPRESS is the vapor pressure (mb * 1000) as computed from temperature,313 # pressure, and dewpoint depression at the same level.314 if param_name == "VAPPRESS":315 array = array / 10.0316 # New unit: Pa317 # SATVAP is the saturation vapor pressure (mb * 1000) as computed from318 # pressure and temperature at the same level.319 if param_name == "SATVAP":320 array = array / 10.0321 # New unit: Pa322 # REPRH is the relative humidity (Percent * 10) as reported in the323 # original sounding.324 if param_name == "REPRH":325 array = array / 10.0326 # New unit: %327 # CALCRH is the relative humidity (Percent * 10) as calculated from vapor328 # pressure, saturation vapor pressure, and pressure at the same329 # level.330 if param_name == "CALCRH":331 array = array / 10.0332 # New unit: %333 # RHGRAD is the relative humidity gradient between the current level and334 # the next higher usable level [(%/km) * 10, positive if relative335 # humidity increases with height].336 if param_name == "RHGRAD":337 array = array / 10000.0338 # New unit: %/m339 # UWND is the zonal wind component [(m/s) * 10] as computed from the340 # reported wind speed and direction.341 if param_name == "UWND":342 array = array / 10.0343 # New unit: m/s344 # UWDGRAD is the vertical gradient of the zonal wind between the current345 # level and the next higher level with a wind observation346 # [(m/s per km) * 10, positive if zonal wind becomes more347 # positive with height].348 if param_name == "UWDGRAD":349 array = array / 10000.0350 # New unit: (m/s) / m351 # VWND is the meridional wind component [(m/s) * 10] as computed352 # from the reported wind speed and direction.353 if param_name == "VWND":354 array = array / 10.0355 # New unit: m/s356 # VWNDGRAD is the vertical gradient of the meridional wind component357 # between the current level and the next higher level with a wind358 # observation [(m/s per km) * 10, positive if the meridional359 # wind becomes more positive with height].360 if param_name == "VWNDGRAD":361 array = array / 10000.0362 # New unit: (m/s) / m363 # N is the refractive index (unitless).364 # Add data to converted data...

Full Screen

Full Screen

header_building_and_parsing.py

Source:header_building_and_parsing.py Github

copy

Full Screen

1__all__ = ()2import re3from .quoting import quote4_TOKEN_RP = re.compile(r'[-!#$%&\'*+.^_`|~0-9a-zA-Z]+')5_LIST_START_RP = re.compile('[\t ,]*')6_SPACE_RP = re.compile('[\t ]*')7_PROTOCOL_RP = re.compile(r'[-!#$%&\'*+.^_`|~0-9a-zA-Z]+(?:/[-!#$%&\'*+.^_`|~0-9a-zA-Z]+)?')8CHARS = frozenset((chr(i) for i in range(0, 128)))9CONTROLS = frozenset((*(chr(i) for i in range(0, 32)), chr(127)))10SEPARATORS = frozenset(('(', ')', '<', '>', '@', ', ', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ',11 chr(9)))12TOKENS = CHARS ^ CONTROLS ^ SEPARATORS13def build_extensions(available_extensions):14 """15 Builds websocket extensions header from the given extension values.16 17 Parameters18 ----------19 available_extensions : `list` of `Any`20 Each websocket extension should have the following `4` attributes / methods:21 - `name`: `str`. The extension's name.22 - `request_params` : `list` of `tuple` (`str`, `str`). Additional header parameters of the extension.23 - `decode` : `callable`. Decoder method, what processes a received websocket frame. Should accept `2`24 parameters: The respective websocket ``Frame``, and the ˙max_size` as `int`, what decides the25 maximal size of a received frame. If it is passed, ``PayloadError`` is raised.26 - `encode` : `callable`. Encoder method, what processes the websocket frames to send. Should accept `1`27 parameter, the respective websocket ``Frame``.28 29 Returns30 -------31 header_value : `str`32 """33 main_parts = []34 sub_parts = []35 36 for available_extension in available_extensions:37 name = available_extension.name38 parameters = available_extension.request_params39 40 sub_parts.append(name)41 for key, value in parameters:42 if value is None:43 sub_parts.append(key)44 else:45 sub_parts.append(f'{key}={value}')46 47 main_parts.append('; '.join(sub_parts))48 sub_parts.clear()49 50 return ', '.join(main_parts)51def parse_extensions(header_value):52 """53 Parses extension header.54 55 Parameters56 ----------57 header_value : `str`58 Received extension header.59 Returns60 -------61 result : `list` of `tuple` (`str`, `list` of `tuple` (`str`, `str`))62 The parsed out extensions as `name` - `parameters` pairs. The `parameters` are in `list` storing63 `key` - `value` pairs.64 65 Raises66 ------67 ValueError68 Extension header value is incorrect.69 """70 result = []71 limit = len(header_value)72 index = 073 74 check_start = True75 76 while True:77 # parse till 1st element78 matched = _LIST_START_RP.match(header_value, index)79 index = matched.end()80 81 # are we at the end?82 if index == limit:83 return result84 85 # now lets parse the extension's name86 matched = _TOKEN_RP.match(header_value, index)87 if matched is None:88 raise ValueError(89 f'Expected extension name since index {index!r}, got {header_value!r}.'90 )91 92 name = matched.group(0)93 index = matched.end()94 95 # nice, we have a name, we can make our item now!96 sub_parts = []97 result.append((name, sub_parts,),)98 99 # should we parse a sublist?100 while True:101 102 # after half item we skip this part103 if check_start:104 # are we at the end?105 if index == limit:106 return result107 108 # lets parse till next character109 matched = _SPACE_RP.match(header_value, index)110 index = matched.end()111 112 # are we at the end?113 if index == limit:114 return result115 116 # no sublist?117 if header_value[index] == ',':118 index += 1119 break120 # invalid character121 if header_value[index] != ';':122 raise ValueError(123 f'Expected \';\' at index {index!r}, got {header_value!r}.'124 )125 126 # we have a sublist127 index += 1128 129 else:130 check_start = True131 132 # parse space133 matched = _SPACE_RP.match(header_value, index)134 index = matched.end()135 136 # are we at the end?137 if index == limit:138 break139 140 # lets parse the key now141 matched = _TOKEN_RP.match(header_value, index)142 if matched is None:143 raise ValueError(144 f'Expected parameter name since index {index!r}, got {header_value!r}.'145 )146 147 key = matched.group(0)148 index = matched.end()149 150 # are we at the end?151 if index == limit:152 sub_parts.append((key, None,),)153 break154 155 # parse space156 matched = _SPACE_RP.match(header_value, index)157 index = matched.end()158 159 # are we at the end?160 if index == limit:161 sub_parts.append((key, None,),)162 break163 #is it a full item or a half?164 165 #next extension166 if header_value[index] == ',':167 sub_parts.append((key, None,),)168 index += 1169 break170 # next item171 if header_value[index] == ';':172 sub_parts.append((key, None,),)173 index += 1174 check_start = False175 continue176 #invalid character177 if header_value[index] != '=':178 raise ValueError(179 f'Expected \',\' or \';\' or \'=\' at index {index!r}, got {header_value!r}.'180 )181 182 index += 1183 184 # parse space185 matched = _SPACE_RP.match(header_value, index)186 index = matched.end()187 188 # are we at the end?189 if index == limit:190 raise ValueError(191 f'Expected a parameter value, but string ended, got {header_value!r}.'192 )193 194 # is it '"stuff"' ?195 if header_value[index] == '"':196 index += 1197 198 # are we at the end?199 if index == limit:200 raise ValueError(201 f'Expected a parameter value, but string ended, got {header_value!r}.'202 )203 204 matched = _TOKEN_RP.match(header_value, index)205 if matched is None:206 raise ValueError(207 f'Expected parameter value since index {index!r}, got {header_value!r}'208 )209 210 value = matched.group(0)211 index = matched.end()212 213 # are we at the end? or did we finish the string normally?214 if index == limit or header_value[index] != '"':215 raise ValueError(216 f'Expected a \'"\' after starting a value with \'"\', got {header_value!r}.'217 )218 index += 1219 220 # is it 'stuff' ?221 else:222 matched = _TOKEN_RP.match(header_value, index)223 if matched is None:224 raise ValueError(225 f'Expected parameter value since index {index!r}, got {header_value!r}.'226 )227 value = matched.group(0)228 index = matched.end()229 230 # we got a full item231 sub_parts.append((key, value,),)232def parse_connections(header_value):233 """234 Parses subprotocol or connection headers.235 236 Parameters237 ----------238 header_value : `str`239 Received subprotocol or connection header.240 241 Returns242 -------243 result : `list` of `str`244 The parsed subprotocol or connection headers.245 246 Raises247 ------248 ValueError249 Subprotocol or connection header value is incorrect.250 """251 result = []252 limit = len(header_value)253 index = 0254 255 while True:256 #parse till 1st element257 matched = _LIST_START_RP.match(header_value, index)258 index = matched.end()259 260 #are we at the end?261 if index == limit:262 return result263 264 #now lets parse the upgrade's name265 matched = _TOKEN_RP.match(header_value, index)266 if matched is None:267 raise ValueError(268 f'Expected upgrade type since index {index!r}, got {header_value!r}.'269 )270 271 name = matched.group(0)272 index = matched.end()273 #nice274 result.append(name)275 276 #are we at the end?277 if index == limit:278 return result279 #lets parse till next character280 matched = _SPACE_RP.match(header_value, index)281 index = matched.end()282 #are we at the end?283 if index == limit:284 return result285 286 #no sublist?287 if header_value[index] == ',':288 index += 1289 continue290 291 raise ValueError(292 f'Expected \',\' at index {index!r}, got {header_value!r}.'293 )294def build_subprotocols(subprotocols):295 """296 Builds websocket subprotocol headers from the given subprotocol values.297 298 Parameters299 ----------300 subprotocols : `list` of `str`301 A list of supported subprotocols.302 303 Returns304 -------305 header_value : `str`306 """307 return ', '.join(subprotocols)308parse_subprotocols = parse_connections # yes, these are the same309def parse_upgrades(header_value):310 """311 Parses upgrade headers.312 313 Parameters314 ----------315 header_value : `str`316 Received upgrade header.317 318 Returns319 -------320 result : `list` of `str`321 The parsed upgrade headers.322 323 Raises324 ------325 ValueError326 Upgrade header value is incorrect.327 """328 result = []329 limit = len(header_value)330 index = 0331 332 while True:333 # parse till 1st element334 matched = _LIST_START_RP.match(header_value, index)335 index = matched.end()336 337 # are we at the end?338 if index == limit:339 return result340 341 # now lets parse the upgrade's name342 matched = _PROTOCOL_RP.match(header_value, index)343 if matched is None:344 raise ValueError(345 f'Expected upgrade type since index {index!r}, got {header_value!r}.'346 )347 name = matched.group(0)348 index = matched.end()349 350 # nice351 result.append(name)352 353 # are we at the end?354 if index == limit:355 return result356 357 # lets parse till next character358 matched = _SPACE_RP.match(header_value, index)359 index = matched.end()360 361 # are we at the end?362 if index == limit:363 return result364 365 # no sublist?366 if header_value[index] == ',':367 index += 1368 continue369 370 raise ValueError(371 f'Expected \',\' at index {index!r}, got {header_value!r}.'372 )373def build_content_disposition_header(disposition_type, parameters, quote_fields):374 """375 Creates Content-Disposition header value.376 377 Parameters378 ----------379 disposition_type : `str`380 Disposition type. Can be one of following: `'inline'`, `'attachment'`, '`form-data`'.381 parameters : `dict` of (`str`, `str`) items382 Disposition parameters.383 quote_fields : `bool`384 Whether field values should be quoted.385 386 Returns387 -------388 value : `str`389 """390 if (not disposition_type) or not (TOKENS > set(disposition_type)):391 raise ValueError(392 f'Bad content disposition type {disposition_type!r}.'393 )394 395 if parameters:396 parameter_parts = [disposition_type]397 for key, value in parameters.items():398 if (not key) or (not (TOKENS > set(key))):399 raise ValueError(400 f'Bad content disposition parameter {key!r}={value!r}.'401 )402 403 if quote_fields:404 value = quote(value, '[]')405 406 parameter_parts.append('; ')407 408 parameter_parts.append(key)409 parameter_parts.append('="')410 parameter_parts.append(value)411 parameter_parts.append('"')412 413 if key == 'filename':414 parameter_parts.append('; filename*=utf-8\'\'')415 parameter_parts.append(value)416 417 value = ''.join(parameter_parts)418 else:419 value = disposition_type420 ...

Full Screen

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Python automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful