@@ -251,7 +251,11 @@ def recv_streaming(self) -> Iterator[Data]:
251
251
"is already running recv or recv_streaming"
252
252
) from None
253
253
254
- def send (self , message : Data | Iterable [Data ]) -> None :
254
+ def send (
255
+ self ,
256
+ message : Data | Iterable [Data ],
257
+ text : bool | None = None ,
258
+ ) -> None :
255
259
"""
256
260
Send a message.
257
261
@@ -262,6 +266,17 @@ def send(self, message: Data | Iterable[Data]) -> None:
262
266
.. _Text: https://datatracker.ietf.org/doc/html/rfc6455#section-5.6
263
267
.. _Binary: https://datatracker.ietf.org/doc/html/rfc6455#section-5.6
264
268
269
+ You may override this behavior with the ``text`` argument:
270
+
271
+ * Set ``text=True`` to send a bytestring or bytes-like object
272
+ (:class:`bytes`, :class:`bytearray`, or :class:`memoryview`) as a
273
+ Text_ frame. This improves performance when the message is already
274
+ UTF-8 encoded, for example if the message contains JSON and you're
275
+ using a JSON library that produces a bytestring.
276
+ * Set ``text=False`` to send a string (:class:`str`) in a Binary_
277
+ frame. This may be useful for servers that expect binary frames
278
+ instead of text frames.
279
+
265
280
:meth:`send` also accepts an iterable of strings, bytestrings, or
266
281
bytes-like objects to enable fragmentation_. Each item is treated as a
267
282
message fragment and sent in its own frame. All items must be of the
@@ -300,7 +315,10 @@ def send(self, message: Data | Iterable[Data]) -> None:
300
315
"cannot call send while another thread "
301
316
"is already running send"
302
317
)
303
- self .protocol .send_text (message .encode ())
318
+ if text is False :
319
+ self .protocol .send_binary (message .encode ())
320
+ else :
321
+ self .protocol .send_text (message .encode ())
304
322
305
323
elif isinstance (message , BytesLike ):
306
324
with self .send_context ():
@@ -309,7 +327,10 @@ def send(self, message: Data | Iterable[Data]) -> None:
309
327
"cannot call send while another thread "
310
328
"is already running send"
311
329
)
312
- self .protocol .send_binary (message )
330
+ if text is True :
331
+ self .protocol .send_text (message )
332
+ else :
333
+ self .protocol .send_binary (message )
313
334
314
335
# Catch a common mistake -- passing a dict to send().
315
336
@@ -328,50 +349,44 @@ def send(self, message: Data | Iterable[Data]) -> None:
328
349
try :
329
350
# First fragment.
330
351
if isinstance (chunk , str ):
331
- text = True
332
352
with self .send_context ():
333
353
if self .send_in_progress :
334
354
raise ConcurrencyError (
335
355
"cannot call send while another thread "
336
356
"is already running send"
337
357
)
338
358
self .send_in_progress = True
339
- self .protocol .send_text (
340
- chunk .encode (),
341
- fin = False ,
342
- )
359
+ if text is False :
360
+ self .protocol .send_binary (chunk .encode (), fin = False )
361
+ else :
362
+ self .protocol .send_text (chunk .encode (), fin = False )
363
+ encode = True
343
364
elif isinstance (chunk , BytesLike ):
344
- text = False
345
365
with self .send_context ():
346
366
if self .send_in_progress :
347
367
raise ConcurrencyError (
348
368
"cannot call send while another thread "
349
369
"is already running send"
350
370
)
351
371
self .send_in_progress = True
352
- self .protocol .send_binary (
353
- chunk ,
354
- fin = False ,
355
- )
372
+ if text is True :
373
+ self .protocol .send_text (chunk , fin = False )
374
+ else :
375
+ self .protocol .send_binary (chunk , fin = False )
376
+ encode = False
356
377
else :
357
378
raise TypeError ("data iterable must contain bytes or str" )
358
379
359
380
# Other fragments
360
381
for chunk in chunks :
361
- if isinstance (chunk , str ) and text :
382
+ if isinstance (chunk , str ) and encode :
362
383
with self .send_context ():
363
384
assert self .send_in_progress
364
- self .protocol .send_continuation (
365
- chunk .encode (),
366
- fin = False ,
367
- )
368
- elif isinstance (chunk , BytesLike ) and not text :
385
+ self .protocol .send_continuation (chunk .encode (), fin = False )
386
+ elif isinstance (chunk , BytesLike ) and not encode :
369
387
with self .send_context ():
370
388
assert self .send_in_progress
371
- self .protocol .send_continuation (
372
- chunk ,
373
- fin = False ,
374
- )
389
+ self .protocol .send_continuation (chunk , fin = False )
375
390
else :
376
391
raise TypeError ("data iterable must contain uniform types" )
377
392
0 commit comments