11from __future__ import annotations
22
3- import abc
43import base64
54import collections
65import datetime
1514from dataclasses import dataclass , field , make_dataclass
1615from datetime import timedelta
1716from typing import (
17+ Annotated ,
1818 ClassVar ,
1919 Deque ,
2020 Dict ,
4444
4545UTC = datetime .timezone .utc
4646
47- PY39 = sys .version_info [:2 ] >= (3 , 9 )
4847PY310 = sys .version_info [:2 ] >= (3 , 10 )
4948PY311 = sys .version_info [:2 ] >= (3 , 11 )
5049PY312 = sys .version_info [:2 ] >= (3 , 12 )
5150
52- py39_plus = pytest .mark .skipif (not PY39 , reason = "3.9+ only" )
5351py310_plus = pytest .mark .skipif (not PY310 , reason = "3.10+ only" )
5452py311_plus = pytest .mark .skipif (not PY311 , reason = "3.11+ only" )
5553py312_plus = pytest .mark .skipif (not PY312 , reason = "3.12+ only" )
@@ -156,7 +154,6 @@ class subclass(cls):
156154
157155
158156class TestDecoder :
159- @py39_plus
160157 def test_decoder_runtime_type_parameters (self , proto ):
161158 dec = proto .Decoder [int ](int )
162159 assert isinstance (dec , proto .Decoder )
@@ -896,8 +893,6 @@ def test_multiple_literals(self):
896893 dec .decode (msgspec .msgpack .encode ("carrot" ))
897894
898895 def test_nested_literals (self ):
899- """Python 3.9+ automatically denest literals, can drop this test when
900- python 3.8 is dropped"""
901896 integers = Literal [- 1 , - 2 , - 3 ]
902897 strings = Literal ["apple" , "banana" ]
903898 both = Literal [integers , strings ]
@@ -2098,10 +2093,6 @@ class Base(cls):
20982093 class Ex (Base , total = False ):
20992094 c : str
21002095
2101- if not hasattr (Ex , "__required_keys__" ):
2102- # This should be Python 3.8, builtin typing only
2103- pytest .skip ("partially optional TypedDict not supported" )
2104-
21052096 dec = proto .Decoder (Ex )
21062097
21072098 x = {"a" : 1 , "b" : "two" , "c" : "extra" }
@@ -2126,10 +2117,6 @@ def test_required_and_notrequired(self, proto, use_typing_extensions):
21262117 if not hasattr (ns , "Required" ):
21272118 pytest .skip (f"{ module } .Required is not available" )
21282119
2129- if not hasattr (ns .TypedDict ("C" , {}), "__required_keys__" ):
2130- # This should be Python 3.8, builtin typing only
2131- pytest .skip ("partially optional TypedDict not supported" )
2132-
21332120 source = f"""
21342121 from __future__ import annotations
21352122 from { module } import TypedDict, Required, NotRequired
@@ -3273,7 +3260,6 @@ def test_encode_time_offset_rounds_to_nearest_minute(self, proto, offset, t_str)
32733260 sol = proto .encode (t_str )
32743261 assert res == sol
32753262
3276- @py39_plus
32773263 def test_encode_time_zoneinfo (self ):
32783264 import zoneinfo
32793265
@@ -3743,23 +3729,23 @@ def test_decode_newtype(self, proto):
37433729 with pytest .raises (ValidationError ):
37443730 proto .decode (proto .encode ("bad" ), type = UserId2 )
37453731
3746- def test_decode_annotated_newtype (self , proto , Annotated ):
3732+ def test_decode_annotated_newtype (self , proto ):
37473733 UserId = NewType ("UserId" , int )
37483734 dec = proto .Decoder (Annotated [UserId , msgspec .Meta (ge = 0 )])
37493735 assert dec .decode (proto .encode (1 )) == 1
37503736
37513737 with pytest .raises (ValidationError ):
37523738 dec .decode (proto .encode (- 1 ))
37533739
3754- def test_decode_newtype_annotated (self , proto , Annotated ):
3740+ def test_decode_newtype_annotated (self , proto ):
37553741 UserId = NewType ("UserId" , Annotated [int , msgspec .Meta (ge = 0 )])
37563742 dec = proto .Decoder (UserId )
37573743 assert dec .decode (proto .encode (1 )) == 1
37583744
37593745 with pytest .raises (ValidationError ):
37603746 dec .decode (proto .encode (- 1 ))
37613747
3762- def test_decode_annotated_newtype_annotated (self , proto , Annotated ):
3748+ def test_decode_annotated_newtype_annotated (self , proto ):
37633749 UserId = Annotated [
37643750 NewType ("UserId" , Annotated [int , msgspec .Meta (ge = 0 )]), msgspec .Meta (le = 10 )
37653751 ]
@@ -3975,10 +3961,9 @@ def test_abstract_sequence(self, proto, typ):
39753961 with pytest .raises (ValidationError , match = "Expected `array`, got `str`" ):
39763962 proto .decode (proto .encode ("a" ), type = typ )
39773963
3978- if PY39 or type (typ ) is not abc .ABCMeta :
3979- assert proto .decode (msg , type = typ [int ]) == sol
3980- with pytest .raises (ValidationError , match = "Expected `int`, got `str`" ):
3981- proto .decode (proto .encode (["a" ]), type = typ [int ])
3964+ assert proto .decode (msg , type = typ [int ]) == sol
3965+ with pytest .raises (ValidationError , match = "Expected `int`, got `str`" ):
3966+ proto .decode (proto .encode (["a" ]), type = typ [int ])
39823967
39833968 @pytest .mark .parametrize (
39843969 "typ" ,
@@ -3996,10 +3981,9 @@ def test_abstract_mapping(self, proto, typ):
39963981 with pytest .raises (ValidationError , match = "Expected `object`, got `str`" ):
39973982 proto .decode (proto .encode ("a" ), type = typ )
39983983
3999- if PY39 or type (typ ) is not abc .ABCMeta :
4000- assert proto .decode (msg , type = typ [str , int ]) == sol
4001- with pytest .raises (ValidationError , match = "Expected `int`, got `str`" ):
4002- proto .decode (proto .encode ({"a" : "b" }), type = typ [str , int ])
3984+ assert proto .decode (msg , type = typ [str , int ]) == sol
3985+ with pytest .raises (ValidationError , match = "Expected `int`, got `str`" ):
3986+ proto .decode (proto .encode ({"a" : "b" }), type = typ [str , int ])
40033987
40043988
40053989class TestUnset :
@@ -4239,7 +4223,7 @@ def test_decode_final(self, proto):
42394223 with pytest .raises (ValidationError ):
42404224 dec .decode (proto .encode ("bad" ))
42414225
4242- def test_decode_final_annotated (self , proto , Annotated ):
4226+ def test_decode_final_annotated (self , proto ):
42434227 dec = proto .Decoder (Final [Annotated [int , msgspec .Meta (ge = 0 )]])
42444228
42454229 assert dec .decode (proto .encode (1 )) == 1
@@ -4323,7 +4307,7 @@ def test_lax_int_from_float(self, proto):
43234307 with pytest .raises (ValidationError , match = "Expected `int`, got `float`" ):
43244308 proto .decode (msg , type = int , strict = False )
43254309
4326- def test_lax_int_constr (self , proto , Annotated ):
4310+ def test_lax_int_constr (self , proto ):
43274311 typ = Annotated [int , Meta (ge = 0 )]
43284312 msg = proto .encode ("1" )
43294313 assert proto .decode (msg , type = typ , strict = False ) == 1
@@ -4370,7 +4354,7 @@ def test_lax_float(self, proto):
43704354 with pytest .raises (ValidationError , match = "Expected `float`, got `str`" ):
43714355 proto .decode (msg , type = float , strict = False )
43724356
4373- def test_lax_float_constr (self , proto , Annotated ):
4357+ def test_lax_float_constr (self , proto ):
43744358 msg = proto .encode ("1.5" )
43754359 assert proto .decode (msg , type = Annotated [float , Meta (ge = 0 )], strict = False ) == 1.5
43764360
@@ -4383,7 +4367,7 @@ def test_lax_str(self, proto):
43834367 msg = proto .encode (x )
43844368 assert proto .decode (msg , type = str , strict = False ) == x
43854369
4386- def test_lax_str_constr (self , proto , Annotated ):
4370+ def test_lax_str_constr (self , proto ):
43874371 typ = Annotated [str , Meta (max_length = 10 )]
43884372 msg = proto .encode ("xxx" )
43894373 assert proto .decode (msg , type = typ , strict = False ) == "xxx"
@@ -4438,7 +4422,7 @@ def test_lax_datetime_invalid_numeric_str(self, proto):
44384422 proto .decode (msg , type = datetime .datetime , strict = False )
44394423
44404424 @pytest .mark .parametrize ("val" , [123 , - 123 , 123.456 , "123.456" ])
4441- def test_lax_datetime_naive_required (self , val , proto , Annotated ):
4425+ def test_lax_datetime_naive_required (self , val , proto ):
44424426 msg = proto .encode (val )
44434427 with pytest .raises (ValidationError , match = "no timezone component" ):
44444428 proto .decode (
@@ -4527,7 +4511,7 @@ def test_lax_union_invalid(self, x, proto):
45274511 ("100.5" , "`float` <= 100.0" ),
45284512 ],
45294513 )
4530- def test_lax_union_invalid_constr (self , x , err , proto , Annotated ):
4514+ def test_lax_union_invalid_constr (self , x , err , proto ):
45314515 """Ensure that values that parse properly but don't meet the specified
45324516 constraints error with a specific constraint error"""
45334517 msg = proto .encode (x )
0 commit comments