@@ -101,6 +101,7 @@ def __init__(self) -> None:
101
101
self ._first : List [_PayloadRegistryItem ] = []
102
102
self ._normal : List [_PayloadRegistryItem ] = []
103
103
self ._last : List [_PayloadRegistryItem ] = []
104
+ self ._normal_lookup : Dict [Any , PayloadType ] = {}
104
105
105
106
def get (
106
107
self ,
@@ -109,12 +110,20 @@ def get(
109
110
_CHAIN : "Type[chain[_PayloadRegistryItem]]" = chain ,
110
111
** kwargs : Any ,
111
112
) -> "Payload" :
113
+ if self ._first :
114
+ for factory , type_ in self ._first :
115
+ if isinstance (data , type_ ):
116
+ return factory (data , * args , ** kwargs )
117
+ # Try the fast lookup first
118
+ if lookup_factory := self ._normal_lookup .get (type (data )):
119
+ return lookup_factory (data , * args , ** kwargs )
120
+ # Bail early if its already a Payload
112
121
if isinstance (data , Payload ):
113
122
return data
114
- for factory , type in _CHAIN (self ._first , self ._normal , self ._last ):
115
- if isinstance (data , type ):
123
+ # Fallback to the slower linear search
124
+ for factory , type_ in _CHAIN (self ._normal , self ._last ):
125
+ if isinstance (data , type_ ):
116
126
return factory (data , * args , ** kwargs )
117
-
118
127
raise LookupError ()
119
128
120
129
def register (
@@ -124,6 +133,11 @@ def register(
124
133
self ._first .append ((factory , type ))
125
134
elif order is Order .normal :
126
135
self ._normal .append ((factory , type ))
136
+ if isinstance (type , Iterable ):
137
+ for t in type :
138
+ self ._normal_lookup [t ] = factory
139
+ else :
140
+ self ._normal_lookup [type ] = factory
127
141
elif order is Order .try_last :
128
142
self ._last .append ((factory , type ))
129
143
else :
@@ -159,7 +173,8 @@ def __init__(
159
173
self ._headers [hdrs .CONTENT_TYPE ] = content_type
160
174
else :
161
175
self ._headers [hdrs .CONTENT_TYPE ] = self ._default_content_type
162
- self ._headers .update (headers or {})
176
+ if headers :
177
+ self ._headers .update (headers )
163
178
164
179
@property
165
180
def size (self ) -> Optional [int ]:
@@ -228,18 +243,17 @@ class BytesPayload(Payload):
228
243
def __init__ (
229
244
self , value : Union [bytes , bytearray , memoryview ], * args : Any , ** kwargs : Any
230
245
) -> None :
231
- if not isinstance (value , (bytes , bytearray , memoryview )):
232
- raise TypeError (f"value argument must be byte-ish, not { type (value )!r} " )
233
-
234
246
if "content_type" not in kwargs :
235
247
kwargs ["content_type" ] = "application/octet-stream"
236
248
237
249
super ().__init__ (value , * args , ** kwargs )
238
250
239
251
if isinstance (value , memoryview ):
240
252
self ._size = value .nbytes
241
- else :
253
+ elif isinstance ( value , ( bytes , bytearray )) :
242
254
self ._size = len (value )
255
+ else :
256
+ raise TypeError (f"value argument must be byte-ish, not { type (value )!r} " )
243
257
244
258
if self ._size > TOO_LARGE_BYTES_BODY :
245
259
kwargs = {"source" : self }
0 commit comments