zmc
2023-08-08 e792e9a60d958b93aef96050644f369feb25d61b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
U
Z±d]ã@sRddlmZmZddlmZmZddlZGdd„dedZGdd„dedZGd    d
„d
edZ    Gd d „d edZ
Gd d„dedZ Gdd„de ƒZ Gdd„de ƒZ Gdd„de e ƒZGdd„deƒZedƒZedddZedddZede ddZGdd „d e eeƒZGd!d"„d"e eeƒZGd#d$„d$e eeƒZGd%d&„d&eeeeƒZdS)'é)ÚABCMetaÚabstractmethod)ÚGenericÚTypeVarNc@s8eZdZdZdZedd„ƒZedd„ƒZedd„ƒZd    S)
ÚClockz)The interface for custom run loop clocks.©cCsdS)zZDo any setup this clock might need.
 
        Called at the beginning of the run.
 
        Nr©Úselfrrú@d:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\trio/_abc.pyÚ start_clockszClock.start_clockcCsdS)zæReturn the current time, according to this clock.
 
        This is used to implement functions like :func:`trio.current_time` and
        :func:`trio.move_on_after`.
 
        Returns:
            float: The current time.
 
        Nrrrrr
Ú current_timeszClock.current_timecCsdS)a¥Compute the real time until the given deadline.
 
        This is called before we enter a system-specific wait function like
        :func:`select.select`, to get the timeout to pass.
 
        For a clock using wall-time, this should be something like::
 
           return deadline - self.current_time()
 
        but of course it may be different if you're implementing some kind of
        virtual clock.
 
        Args:
            deadline (float): The absolute time of the next deadline,
                according to this clock.
 
        Returns:
            float: The number of real seconds to sleep until the given
            deadline. May be :data:`math.inf`.
 
        Nr)r    Údeadlinerrr
Údeadline_to_sleep_time#szClock.deadline_to_sleep_timeN)    Ú__name__Ú
__module__Ú __qualname__Ú__doc__Ú    __slots__rr r rrrrr
r
s
 
r)Ú    metaclassc@s\eZdZdZdZdd„Zdd„Zdd„Zd    d
„Zd d „Z    d d„Z
dd„Z dd„Z dd„Z dS)Ú
InstrumentzÍThe interface for run loop instrumentation.
 
    Instruments don't have to inherit from this abstract base class, and all
    of these methods are optional. This class serves mostly as documentation.
 
    rcCsdS)z,Called at the beginning of :func:`trio.run`.Nrrrrr
Ú
before_runFszInstrument.before_runcCsdS)z,Called just before :func:`trio.run` returns.Nrrrrr
Ú    after_runIszInstrument.after_runcCsdS)ztCalled when the given task is created.
 
        Args:
            task (trio.lowlevel.Task): The new task.
 
        Nr©r    Ztaskrrr
Ú task_spawnedLszInstrument.task_spawnedcCsdS)zþCalled when the given task becomes runnable.
 
        It may still be some time before it actually runs, if there are other
        runnable tasks ahead of it.
 
        Args:
            task (trio.lowlevel.Task): The task that became runnable.
 
        Nrrrrr
Útask_scheduledTszInstrument.task_scheduledcCsdS)zšCalled immediately before we resume running the given task.
 
        Args:
            task (trio.lowlevel.Task): The task that is about to run.
 
        Nrrrrr
Úbefore_task_step_szInstrument.before_task_stepcCsdS)zœCalled when we return to the main run loop after a task has yielded.
 
        Args:
            task (trio.lowlevel.Task): The task that just ran.
 
        Nrrrrr
Úafter_task_stepgszInstrument.after_task_stepcCsdS)ztCalled when the given task exits.
 
        Args:
            task (trio.lowlevel.Task): The finished task.
 
        Nrrrrr
Ú task_exitedoszInstrument.task_exitedcCsdS)z•Called before blocking to wait for I/O readiness.
 
        Args:
            timeout (float): The number of seconds we are willing to wait.
 
        Nr©r    Útimeoutrrr
Úbefore_io_waitwszInstrument.before_io_waitcCsdS)zûCalled after handling pending I/O.
 
        Args:
            timeout (float): The number of seconds we were willing to
                wait. This much time may or may not have elapsed, depending on
                whether any I/O was ready.
 
        Nrrrrr
Ú after_io_waitszInstrument.after_io_waitN)rrrrrrrrrrrrr r!rrrr
r<s rc@s.eZdZdZdZed    dd„ƒZedd„ƒZdS)
ÚHostnameResolverzÈIf you have a custom hostname resolver, then implementing
    :class:`HostnameResolver` allows you to register this to be used by Trio.
 
    See :func:`trio.socket.set_custom_hostname_resolver`.
 
    rrcÃsdS)uA custom implementation of :func:`~trio.socket.getaddrinfo`.
 
        Called by :func:`trio.socket.getaddrinfo`.
 
        If ``host`` is given as a numeric IP address, then
        :func:`~trio.socket.getaddrinfo` may handle the request itself rather
        than calling this method.
 
        Any required IDNA encoding is handled before calling this function;
        your implementation can assume that it will never see U-labels like
        ``"café.com"``, and only needs to handle A-labels like
        ``b"xn--caf-dma.com"``.
 
        Nr)r    ÚhostÚportÚfamilyÚtypeÚprotoÚflagsrrr
Ú getaddrinfo”szHostnameResolver.getaddrinfocÃsdS)zzA custom implementation of :func:`~trio.socket.getnameinfo`.
 
        Called by :func:`trio.socket.getnameinfo`.
 
        Nr)r    Zsockaddrr(rrr
Ú getnameinfo¥szHostnameResolver.getnameinfoN)rrrr)rrrrrrr)r*rrrr
r"Šs  r"c@seZdZdZeddd„ƒZdS)Ú SocketFactoryzÆIf you write a custom class implementing the Trio socket interface,
    then you can use a :class:`SocketFactory` to get Trio to use it.
 
    See :func:`trio.socket.set_custom_socket_factory`.
 
    NcCsdS)a&Create and return a socket object.
 
        Your socket object must inherit from :class:`trio.socket.SocketType`,
        which is an empty class whose only purpose is to "mark" which classes
        should be considered valid Trio sockets.
 
        Called by :func:`trio.socket.socket`.
 
        Note that unlike :func:`trio.socket.socket`, this does not take a
        ``fileno=`` argument. If a ``fileno=`` is specified, then
        :func:`trio.socket.socket` returns a regular Trio socket object
        instead of calling this method.
 
        Nr)r    r%r&r'rrr
Úsocket¶szSocketFactory.socket)NNN)rrrrrr,rrrr
r+®sr+c@s0eZdZdZdZedd„ƒZdd„Zdd„Zd    S)
Ú AsyncResourcea‹A standard interface for resources that needs to be cleaned up, and
    where that cleanup may require blocking operations.
 
    This class distinguishes between "graceful" closes, which may perform I/O
    and thus block, and a "forceful" close, which cannot. For example, cleanly
    shutting down a TLS-encrypted connection requires sending a "goodbye"
    message; but if a peer has become non-responsive, then sending this
    message might block forever, so we may want to just drop the connection
    instead. Therefore the :meth:`aclose` method is unusual in that it
    should always close the connection (or at least make its best attempt)
    *even if it fails*; failure indicates a failure to achieve grace, not a
    failure to close the connection.
 
    Objects that implement this interface can be used as async context
    managers, i.e., you can write::
 
      async with create_resource() as some_async_resource:
          ...
 
    Entering the context manager is synchronous (not a checkpoint); exiting it
    calls :meth:`aclose`. The default implementations of
    ``__aenter__`` and ``__aexit__`` should be adequate for all subclasses.
 
    rcÃsdS)aÓClose this resource, possibly blocking.
 
        IMPORTANT: This method may block in order to perform a "graceful"
        shutdown. But, if this fails, then it still *must* close any
        underlying resources before returning. An error from this method
        indicates a failure to achieve grace, *not* a failure to close the
        connection.
 
        For example, suppose we call :meth:`aclose` on a TLS-encrypted
        connection. This requires sending a "goodbye" message; but if the peer
        has become non-responsive, then our attempt to send this message might
        block forever, and eventually time out and be cancelled. In this case
        the :meth:`aclose` method on :class:`~trio.SSLStream` will
        immediately close the underlying transport stream using
        :func:`trio.aclose_forcefully` before raising :exc:`~trio.Cancelled`.
 
        If the resource is already closed, then this method should silently
        succeed.
 
        Once this method completes, any other pending or future operations on
        this resource should generally raise :exc:`~trio.ClosedResourceError`,
        unless there's a good reason to do otherwise.
 
        See also: :func:`trio.aclose_forcefully`.
 
        Nrrrrr
ÚacloseäszAsyncResource.aclosecÃs|S©Nrrrrr
Ú
__aenter__szAsyncResource.__aenter__cÇs| ¡IdHdSr/)r.)r    Úargsrrr
Ú    __aexit__szAsyncResource.__aexit__N)    rrrrrrr.r0r2rrrr
r-Ès 
r-c@s,eZdZdZdZedd„ƒZedd„ƒZdS)Ú
SendStreama(A standard interface for sending data on a byte stream.
 
    The underlying stream may be unidirectional, or bidirectional. If it's
    bidirectional, then you probably want to also implement
    :class:`ReceiveStream`, which makes your object a :class:`Stream`.
 
    :class:`SendStream` objects also implement the :class:`AsyncResource`
    interface, so they can be closed by calling :meth:`~AsyncResource.aclose`
    or using an ``async with`` block.
 
    If you want to send Python objects rather than raw bytes, see
    :class:`SendChannel`.
 
    rcÃsdS)aiSends the given data through the stream, blocking if necessary.
 
        Args:
          data (bytes, bytearray, or memoryview): The data to send.
 
        Raises:
          trio.BusyResourceError: if another task is already executing a
              :meth:`send_all`, :meth:`wait_send_all_might_not_block`, or
              :meth:`HalfCloseableStream.send_eof` on this stream.
          trio.BrokenResourceError: if something has gone wrong, and the stream
              is broken.
          trio.ClosedResourceError: if you previously closed this stream
              object, or if another task closes this stream object while
              :meth:`send_all` is running.
 
        Most low-level operations in Trio provide a guarantee: if they raise
        :exc:`trio.Cancelled`, this means that they had no effect, so the
        system remains in a known state. This is **not true** for
        :meth:`send_all`. If this operation raises :exc:`trio.Cancelled` (or
        any other exception for that matter), then it may have sent some, all,
        or none of the requested data, and there is no way to know which.
 
        Nr©r    Údatarrr
Úsend_allszSendStream.send_allcÃsdS)aÆ
Block until it's possible that :meth:`send_all` might not block.
 
        This method may return early: it's possible that after it returns,
        :meth:`send_all` will still block. (In the worst case, if no better
        implementation is available, then it might always return immediately
        without blocking. It's nice to do better than that when possible,
        though.)
 
        This method **must not** return *late*: if it's possible for
        :meth:`send_all` to complete without blocking, then it must
        return. When implementing it, err on the side of returning early.
 
        Raises:
          trio.BusyResourceError: if another task is already executing a
              :meth:`send_all`, :meth:`wait_send_all_might_not_block`, or
              :meth:`HalfCloseableStream.send_eof` on this stream.
          trio.BrokenResourceError: if something has gone wrong, and the stream
              is broken.
          trio.ClosedResourceError: if you previously closed this stream
              object, or if another task closes this stream object while
              :meth:`wait_send_all_might_not_block` is running.
 
        Note:
 
          This method is intended to aid in implementing protocols that want
          to delay choosing which data to send until the last moment. E.g.,
          suppose you're working on an implementation of a remote display server
          like `VNC
          <https://en.wikipedia.org/wiki/Virtual_Network_Computing>`__, and
          the network connection is currently backed up so that if you call
          :meth:`send_all` now then it will sit for 0.5 seconds before actually
          sending anything. In this case it doesn't make sense to take a
          screenshot, then wait 0.5 seconds, and then send it, because the
          screen will keep changing while you wait; it's better to wait 0.5
          seconds, then take the screenshot, and then send it, because this
          way the data you deliver will be more
          up-to-date. Using :meth:`wait_send_all_might_not_block` makes it
          possible to implement the better strategy.
 
          If you use this method, you might also want to read up on
          ``TCP_NOTSENT_LOWAT``.
 
          Further reading:
 
          * `Prioritization Only Works When There's Pending Data to Prioritize
            <https://insouciant.org/tech/prioritization-only-works-when-theres-pending-data-to-prioritize/>`__
 
          * WWDC 2015: Your App and Next Generation Networks: `slides
            <http://devstreaming.apple.com/videos/wwdc/2015/719ui2k57m/719/719_your_app_and_next_generation_networks.pdf?dl=1>`__,
            `video and transcript
            <https://developer.apple.com/videos/play/wwdc2015/719/>`__
 
        Nrrrrr
Úwait_send_all_might_not_block4sz(SendStream.wait_send_all_might_not_blockN)rrrrrrr6r7rrrr
r3s 
r3c@s2eZdZdZdZed
dd„ƒZdd„Zdd    „ZdS) Ú ReceiveStreamaSA standard interface for receiving data on a byte stream.
 
    The underlying stream may be unidirectional, or bidirectional. If it's
    bidirectional, then you probably want to also implement
    :class:`SendStream`, which makes your object a :class:`Stream`.
 
    :class:`ReceiveStream` objects also implement the :class:`AsyncResource`
    interface, so they can be closed by calling :meth:`~AsyncResource.aclose`
    or using an ``async with`` block.
 
    If you want to receive Python objects rather than raw bytes, see
    :class:`ReceiveChannel`.
 
    `ReceiveStream` objects can be used in ``async for`` loops. Each iteration
    will produce an arbitrary sized chunk of bytes, like calling
    `receive_some` with no arguments. Every chunk will contain at least one
    byte, and the loop automatically exits when reaching end-of-file.
 
    rNcÃsdS)a4Wait until there is data available on this stream, and then return
        some of it.
 
        A return value of ``b""`` (an empty bytestring) indicates that the
        stream has reached end-of-file. Implementations should be careful that
        they return ``b""`` if, and only if, the stream has reached
        end-of-file!
 
        Args:
          max_bytes (int): The maximum number of bytes to return. Must be
              greater than zero. Optional; if omitted, then the stream object
              is free to pick a reasonable default.
 
        Returns:
          bytes or bytearray: The data received.
 
        Raises:
          trio.BusyResourceError: if two tasks attempt to call
              :meth:`receive_some` on the same stream at the same time.
          trio.BrokenResourceError: if something has gone wrong, and the stream
              is broken.
          trio.ClosedResourceError: if you previously closed this stream
              object, or if another task closes this stream object while
              :meth:`receive_some` is running.
 
        Nr)r    Z    max_bytesrrr
Ú receive_some„szReceiveStream.receive_somecCs|Sr/rrrrr
Ú    __aiter__¡szReceiveStream.__aiter__cÃs| ¡IdH}|st‚|Sr/)r9ÚStopAsyncIterationr4rrr
Ú    __anext__¤szReceiveStream.__anext__)N)    rrrrrrr9r:r<rrrr
r8ms  r8c@seZdZdZdZdS)ÚStreamaTA standard interface for interacting with bidirectional byte streams.
 
    A :class:`Stream` is an object that implements both the
    :class:`SendStream` and :class:`ReceiveStream` interfaces.
 
    If implementing this interface, you should consider whether you can go one
    step further and implement :class:`HalfCloseableStream`.
 
    rN)rrrrrrrrr
r=«s
r=c@s eZdZdZdZedd„ƒZdS)ÚHalfCloseableStreamz„This interface extends :class:`Stream` to also allow closing the send
    part of the stream without closing the receive part.
 
    rcÃsdS)u    Send an end-of-file indication on this stream, if possible.
 
        The difference between :meth:`send_eof` and
        :meth:`~AsyncResource.aclose` is that :meth:`send_eof` is a
        *unidirectional* end-of-file indication. After you call this method,
        you shouldn't try sending any more data on this stream, and your
        remote peer should receive an end-of-file indication (eventually,
        after receiving all the data you sent before that). But, they may
        continue to send data to you, and you can continue to receive it by
        calling :meth:`~ReceiveStream.receive_some`. You can think of it as
        calling :meth:`~AsyncResource.aclose` on just the
        :class:`SendStream` "half" of the stream object (and in fact that's
        literally how :class:`trio.StapledStream` implements it).
 
        Examples:
 
        * On a socket, this corresponds to ``shutdown(..., SHUT_WR)`` (`man
          page <https://linux.die.net/man/2/shutdown>`__).
 
        * The SSH protocol provides the ability to multiplex bidirectional
          "channels" on top of a single encrypted connection. A Trio
          implementation of SSH could expose these channels as
          :class:`HalfCloseableStream` objects, and calling :meth:`send_eof`
          would send an ``SSH_MSG_CHANNEL_EOF`` request (see `RFC 4254 Â§5.3
          <https://tools.ietf.org/html/rfc4254#section-5.3>`__).
 
        * On an SSL/TLS-encrypted connection, the protocol doesn't provide any
          way to do a unidirectional shutdown without closing the connection
          entirely, so :class:`~trio.SSLStream` implements
          :class:`Stream`, not :class:`HalfCloseableStream`.
 
        If an EOF has already been sent, then this method should silently
        succeed.
 
        Raises:
          trio.BusyResourceError: if another task is already executing a
              :meth:`~SendStream.send_all`,
              :meth:`~SendStream.wait_send_all_might_not_block`, or
              :meth:`send_eof` on this stream.
          trio.BrokenResourceError: if something has gone wrong, and the stream
              is broken.
          trio.ClosedResourceError: if you previously closed this stream
              object, or if another task closes this stream object while
              :meth:`send_eof` is running.
 
        Nrrrrr
Úsend_eofÁszHalfCloseableStream.send_eofN)rrrrrrr?rrrr
r>¹sr>ÚTÚ ReceiveTypeT)Ú    covariantÚSendType)Ú contravariantÚ
T_resource)ÚboundrBc@s eZdZdZdZedd„ƒZdS)ÚListenerzÿA standard interface for listening for incoming connections.
 
    :class:`Listener` objects also implement the :class:`AsyncResource`
    interface, so they can be closed by calling :meth:`~AsyncResource.aclose`
    or using an ``async with`` block.
 
    rcÃsdS)uŠWait until an incoming connection arrives, and then return it.
 
        Returns:
          AsyncResource: An object representing the incoming connection. In
          practice this is generally some kind of :class:`Stream`,
          but in principle you could also define a :class:`Listener` that
          returned, say, channel objects.
 
        Raises:
          trio.BusyResourceError: if two tasks attempt to call
              :meth:`accept` on the same listener at the same time.
          trio.ClosedResourceError: if you previously closed this listener
              object, or if another task closes this listener object while
              :meth:`accept` is running.
 
        Listeners don't generally raise :exc:`~trio.BrokenResourceError`,
        because for listeners there is no general condition of "the
        network/remote peer broke the connection" that can be handled in a
        generic way, like there is for streams. Other errors *can* occur and
        be raised from :meth:`accept` â€“ for example, if you run out of file
        descriptors then you might get an :class:`OSError` with its errno set
        to ``EMFILE``.
 
        Nrrrrr
ÚacceptszListener.acceptN)rrrrrrrHrrrr
rGsrGc@s(eZdZdZdZeeddœdd„ƒZdS)Ú SendChannelaHA standard interface for sending Python objects to some receiver.
 
    `SendChannel` objects also implement the `AsyncResource` interface, so
    they can be closed by calling `~AsyncResource.aclose` or using an ``async
    with`` block.
 
    If you want to send raw bytes rather than Python objects, see
    `SendStream`.
 
    rN)ÚvalueÚreturncÃsdS)aDAttempt to send an object through the channel, blocking if necessary.
 
        Args:
          value (object): The object to send.
 
        Raises:
          trio.BrokenResourceError: if something has gone wrong, and the
              channel is broken. For example, you may get this if the receiver
              has already been closed.
          trio.ClosedResourceError: if you previously closed this
              :class:`SendChannel` object, or if another task closes it while
              :meth:`send` is running.
          trio.BusyResourceError: some channels allow multiple tasks to call
              `send` at the same time, but others don't. If you try to call
              `send` simultaneously from multiple tasks on a channel that
              doesn't support it, then you can get `~trio.BusyResourceError`.
 
        Nr)r    rJrrr
Úsend:szSendChannel.send)rrrrrrrCrLrrrr
rI,s rIc@s<eZdZdZdZeedœdd„ƒZdd„Zedœdd    „Z    d
S) ÚReceiveChannelapA standard interface for receiving Python objects from some sender.
 
    You can iterate over a :class:`ReceiveChannel` using an ``async for``
    loop::
 
       async for value in receive_channel:
           ...
 
    This is equivalent to calling :meth:`receive` repeatedly. The loop exits
    without error when `receive` raises `~trio.EndOfChannel`.
 
    `ReceiveChannel` objects also implement the `AsyncResource` interface, so
    they can be closed by calling `~AsyncResource.aclose` or using an ``async
    with`` block.
 
    If you want to receive raw bytes rather than Python objects, see
    `ReceiveStream`.
 
    r)rKcÃsdS)a=Attempt to receive an incoming object, blocking if necessary.
 
        Returns:
          object: Whatever object was received.
 
        Raises:
          trio.EndOfChannel: if the sender has been closed cleanly, and no
              more objects are coming. This is not an error condition.
          trio.ClosedResourceError: if you previously closed this
              :class:`ReceiveChannel` object.
          trio.BrokenResourceError: if something has gone wrong, and the
              channel is broken.
          trio.BusyResourceError: some channels allow multiple tasks to call
              `receive` at the same time, but others don't. If you try to call
              `receive` simultaneously from multiple tasks on a channel that
              doesn't support it, then you can get `~trio.BusyResourceError`.
 
        Nrrrrr
ÚreceivegszReceiveChannel.receivecCs|Sr/rrrrr
r:|szReceiveChannel.__aiter__cÃs0z| ¡IdHWStjk
r*t‚YnXdSr/)rNÚtrioZ EndOfChannelr;rrrr
r<szReceiveChannel.__anext__N)
rrrrrrrArNr:r<rrrr
rMPs rMc@seZdZdZdS)ÚChannelzÛA standard interface for interacting with bidirectional channels.
 
    A `Channel` is an object that implements both the `SendChannel` and
    `ReceiveChannel` interfaces, so you can both send and receive objects.
 
    N)rrrrrrrr
rP†srP)ÚabcrrÚtypingrrrOrrr"r+r-r3r8r=r>r@rArCrErGrIrMrPrrrr
Ú<module>s&2N$@e>;  '$6