cs.packetstream


Namecs.packetstream JSON
Version 20240630 PyPI version JSON
download
home_pageNone
Summarygeneral purpose bidirectional packet stream connection
upload_time2024-06-30 02:06:11
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseGNU General Public License v3 or later (GPLv3+)
keywords python2 python3
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            A general purpose bidirectional packet stream connection.

*Latest release 20240630*:
* New ERQ_Packet to indicate end of client requests.
* PacketConnection.startup_shutdown: send ERQ_Packet at stream shutdown.
* New PacketConnection.end_requests() method to queue an ERQ_Packet to the send queue.
* PacketConnection: send the EOF_Packet from the send worker instead of from startup_shutdown.
* Rename PacketConnection.do to PacketConnection.__call__.
* PacketStream: BREAKING: replace the recv and send parameters with a singe recv_send parameter.
* PacketStream: do not close supplied connection handles - this allows reuse of an underlying binary connection.
* Many many logic fixes for clean and orderly shutdown.
* Rename PacketConnection.request to PacketConnection.submit.
* New BaseRequest and HasPacketConnection helper classes to make it easy to use a PacketConnection for a protocol.

## Class `BaseRequest(cs.binary.AbstractBinary)`

A base class for request classes to use with `HasPacketConnection`.

This is a mixin aimed at `*Binary` classes representing the
request payload and supplies an `__init__` method which saves
the optional `flags` parameter as `.flags` and passes all
other parameters to the superclass' `__init__`
(the `*Binary` superclass).

As such, it is important to define the subclass like this:

    class AddRequest(
        BaseRequest,
        BinaryMultiValue('AddRequest', dict(hashenum=BSUInt, data=BSData)),
    ):

with `BaseRequest` _first_ if you wish to omit an `__init__` method.

Subclasses must implement the `fulfil` method to perform the
request operation.

Often a subclass will also implement the
`decode_response_payload(flags,payload)` method.
This provides the result of a request, returned by
`HasPacketConnection.conn_do_remote` or by the `Result`
returned from `HasPacketConnection.conn_submit`.
The default returns the response `flags` and `payload` directly.

This base class subclasses `AbstractBinary` to encode and
decode the request `payload` and has an additions `flags`
attribute for the `Packet.flags`.  As such, subclasses have
two main routes for implemetation:

1: Subclass an existing `AbstractBinary` subclass. For example,
   the `cs.vt.stream.ContainsRequest` looks up a hash code, and
   subclasses the `cs.vt.hash.HashField` class.

2: Provide a `parse(bfr)` factory method and `transcribe()`
   method to parse and transcribe the request `payload` like any
   other `AbstractBinary` subclass.

Approach 1 does not necessarily need a distinct class;
a binary class can often be constructed in the class header.
For example, the `cs.vt.stream.AddRequest` payload is an `int`
representing the hash class and the data to add. The class
header looks like this:

    class AddRequest(
        BaseRequest,
        BinaryMultiValue('AddRequest', dict(hashenum=BSUInt, data=BSData)),
    ):

much as one might subclass a `namedtuple` in other circumstances.

*Method `BaseRequest.decode_response_payload(self, flags: int, payload: bytes)`*:
Decode a _response_ `flags` and `payload`.

This default implementation returns the `flags` and `payload` unchanged.

*Method `BaseRequest.from_request_payload(flags: int, payload: bytes) -> 'BaseRequest'`*:
Decode a _request_ `flags` and `payload`, return a `BaseRequest` instance.

This is called with the correct `BaseRequest` subclass
derived from the received `Packet.rq_type`.
It decodes the 

This default implementation assumes that `flags==0`
and calls `cls.from_bytes(payload)`.

*Method `BaseRequest.fulfil(self, context) -> Union[NoneType, int, bytes, str, Tuple[int, bytes]]`*:
Fulfil this request at the receiving end of the connection using
`context`, some outer object using the connection.
Raise an exception if the request cannot be fulfilled.

Return values suitable for the response:
* `None`: equivalent to `(0,b'')`
* `int`: returned in the flags with `b''` for the payload
* `bytes`: returned as the payload with `0` as the flags
* `str`: return `encode(s,'ascii')` as the payload with `0` as the flags
* `(int,bytes)`: the flags and payload

A typical implementation looks like this:

    def fulfil(self, context):
        return context.come_method(params...)

where `params` come from the request attributes.

## Class `HasPacketConnection`

This is a mixin class to aid writing classes which use a
`PacketConnection` to communicate with some service.

The supported request/response packet types are provided as
a mapping of `int` `Packet.rq_type` values to a class
implementing that request type, a subclass of `BaseRequest`.

For example, a `cs.vt.stream.StreamStore` subclasses `HasPacketConnection`
and initialises the mixin with this call:

    HasPacketConnection.__init__(
        self,
        recv_send,
        name,
        { 0: AddRequest,  # add chunk, return hashcode
          1: GetRequest,  # get chunk from hashcode
          .......
        },
    )

See the `BaseRequest` class for details on how to implement
each request type.

*Method `HasPacketConnection.__init__(self, recv_send: Union[Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile]], Callable[[], Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile], Callable[[], NoneType]]]], name: str = None, *, rq_type_map: Mapping[int, cs.packetstream.BaseRequest], **packet_kw)`*:
Initialise `self.conn` as a `PacketConnection`.

Parameters:
* `recv_send`: as for `PacketConnection`
* `name`: an optional name for the connection
* `rq_type_map`: a mapping of request types to `BaseRequest` subclasses

Other keyword arguments are passed to `PacketConnection()`.

*Method `HasPacketConnection.conn_do_remote(self, rq: cs.packetstream.BaseRequest, **submit_kw)`*:
Run `rq` remotely.
Raises `ValueError` if the response is not ok.
Otherwise returns `rq.decode_response(flags, payload)`.

*Method `HasPacketConnection.conn_handle_request(self, rq_type: int, flags: int, payload: bytes)`*:
Handle receipt of a request packet.
Decode the packet into a request `rq` and return `rq.fulfil(self)`.

*Method `HasPacketConnection.conn_submit(self, rq: cs.packetstream.BaseRequest, *, channel=0, label=None) -> cs.result.Result`*:
Submit this request to the connection, return a `Result`.

## Class `Packet(cs.binary.SimpleBinary)`

A protocol packet.

*Method `Packet.__str__(self)`*:
pylint: disable=signature-differs

*Method `Packet.parse(bfr, log=None)`*:
Parse a `Packet` from a buffer.

*Method `Packet.transcribe(self)`*:
Transcribe this packet.

*Method `Packet.write(self, file, flush=False, log=None)`*:
Write the `Packet` to `file`.

## Class `PacketConnection(cs.resources.MultiOpenMixin)`

A bidirectional binary connection for exchanging requests and responses.

*Method `PacketConnection.__init__(self, recv_send: Union[Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile]], Callable[[], Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile], Callable[[], NoneType]]]], name=None, *, request_handler=None, packet_grace=None, trace_log: Optional[Callable] = None)`*:
Initialise the `PacketConnection`.

Parameters:
* `recv_send`: specify the receive and send streams
* `packet_grace`:
  default pause in the packet sending worker
  to allow another packet to be queued
  before flushing the output stream.
  Default: `DEFAULT_PACKET_GRACE`s.
  A value of `0` will flush immediately if the queue is empty.
* `request_handler`: an optional callable accepting
  (`rq_type`, `flags`, `payload`).
  The request_handler may return one of 5 values on success:
  * `None`: response will be 0 flags and an empty payload.
  * `int`: flags only. Response will be the flags and an empty payload.
  * `bytes`: payload only. Response will be 0 flags and the payload.
  * `str`: payload only. Response will be 0 flags and the str
          encoded as bytes using UTF-8.
  * `(int, bytes)`: Specify flags and payload for response.
  An unsuccessful request should raise an exception, which
  will cause a failure response packet.

The `recv_send` parameter is used to prepare the connection.
It may take the following forms:
* a 2-tuple of `(recv,send)` specifying the receive and send streams
* an `int` specifying a single file descriptor used for
  both receive and send
* a callable returning a 3-tuple of `(recv,send,close)` as
  for `PacketConnection`'s callable mode
The `(recv,send)` pair indicate the inbound and outbound binary streams.

For preexisting streams such as pipes or sockets these can be:
* `recv`: anything acceptable to `CornuCopyBuffer.promote()`,
  typically a file descriptor or a binary file with `.write`
  and `.flush` methods.
* `send`: a file descriptor or a binary file with `.write`
  and `.flush` methods.

For "on demand" use, `recv` may be a callable and `send` may be `None`.
In this case, `recv()` must return a 3-tuple of
`(recv,send,shutdown)` being values for `recv` and `send`
as above, and a shutdown function to do the necessary "close"
of the new `recv` and `send`. `shutdown` may be `None` if there is
no meaningful close operation.
The `PacketConnection`'s `startup_shutdown` method will
call `recv()` to obtain the binary streams and call the
`shutdown` on completion.
This supports use for on demand connections, eg:

    P = PacketConnection(connect_to_server)
    ......
    with P:
        ... use P to to work ...

where `connect_to_server()` might connect to some remote service.

*Method `PacketConnection.__call__(self, rq_type, payload=b'', flags=0, *, decode_response=None, channel=0, label=None)`*:
Calling the `PacketConnection` performs a synchronous request.
Submits the request, then calls the `Result` returned from the request.

*Method `PacketConnection.join(self)`*:
Wait for the send and receive workers to terminate.

*Method `PacketConnection.join_recv(self)`*:
Wait for the end of the receive worker.
Servers should call this.

*Method `PacketConnection.send_eof(self)`*:
Queue the magic EOF `Packet`.

*Method `PacketConnection.send_erq(self)`*:
Queue the magic end-of-requests `Packet`.

*Method `PacketConnection.submit(self, rq_type: int, flags: int = 0, payload: bytes = b'', *, decode_response=None, channel=0, label=None) -> cs.result.Result`*:
Compose and dispatch a new request, returns a `Result`.

Allocates a new tag, a `Result` to deliver the response, and
records the response decode function for use when the
response arrives.

Parameters:
* `rq_type`: request type code, an `int`
* `flags`: optional flags to accompany the request, an int;
  default `0`.
* `payload`: optional bytes-like object to accompany the request;
  default `b''`
* `decode_response`: optional callable accepting (response_flags,
  response_payload_bytes) and returning the decoded response payload
  value; if unspecified, the response payload bytes are used
* `label`: optional label for this request to aid debugging

The `Result` will yield an `(ok, flags, payload)` tuple, where:
* `ok`: whether the request was successful
* `flags`: the response flags
* `payload`: the response payload, decoded by decode_response
  if specified

## Class `ReadableFile(typing.Protocol)`

The requirements for a file used to receive.

*Method `ReadableFile.__subclasshook__(other)`*:
Set (or override) the protocol subclass hook.

*Method `ReadableFile.read(self, size: int) -> bytes`*:
Read up to `size` bytes.

## Class `RequestState(RequestState)`

A state object tracking a particular request.

*Method `RequestState.cancel(self)`*:
Cancel this request.

*Method `RequestState.complete(self, flags, payload)`*:
Complete the request from an "ok" `flags` and `payload`.

*Method `RequestState.fail(self, flags, payload)`*:
Fail the request from a "not ok" `flags` and `payload`.

## Class `SendableFile(typing.Protocol)`

The requirements for a file used to send.

*Method `SendableFile.__subclasshook__(other)`*:
Set (or override) the protocol subclass hook.

*Method `SendableFile.flush(self) -> None`*:
Flush any buffer of written bytes.

*Method `SendableFile.write(self, bs: bytes) -> int`*:
Write bytes, return the number of bytes written.

# Release Log



*Release 20240630*:
* New ERQ_Packet to indicate end of client requests.
* PacketConnection.startup_shutdown: send ERQ_Packet at stream shutdown.
* New PacketConnection.end_requests() method to queue an ERQ_Packet to the send queue.
* PacketConnection: send the EOF_Packet from the send worker instead of from startup_shutdown.
* Rename PacketConnection.do to PacketConnection.__call__.
* PacketStream: BREAKING: replace the recv and send parameters with a singe recv_send parameter.
* PacketStream: do not close supplied connection handles - this allows reuse of an underlying binary connection.
* Many many logic fixes for clean and orderly shutdown.
* Rename PacketConnection.request to PacketConnection.submit.
* New BaseRequest and HasPacketConnection helper classes to make it easy to use a PacketConnection for a protocol.

*Release 20240412*:
* PacketConnection: now subclasses MultiOpenMixin, big refactor.
* PacketConnection.__init__: use @promote to turn the recv parameter into a CornuCopyBuffer.
* Fix a deadlock.

*Release 20211208*:
* Packet.__eq__: only test .rq_type if .is_request.
* Update tests for changes.

*Release 20210306*:
* Port to new cs.binary.Binary* classes.
* Some refactors and small fixes.

*Release 20191004*:
* PacketConnection: new optional parameter `packet_grace` to tune the send delay for additional packets before a flush, default DEFAULT_PACKET_GRACE (0.01s), 0 for no delay.
* Add a crude packet level activity ticker.

*Release 20190221*:
DISTINFO requirement updates.

*Release 20181228*:
Initial PyPI release.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "cs.packetstream",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python2, python3",
    "author": null,
    "author_email": "Cameron Simpson <cs@cskk.id.au>",
    "download_url": "https://files.pythonhosted.org/packages/31/da/6252b713fa3efa66539e259d7e9df3a886c21bd10709808d14736dbca236/cs.packetstream-20240630.tar.gz",
    "platform": null,
    "description": "A general purpose bidirectional packet stream connection.\n\n*Latest release 20240630*:\n* New ERQ_Packet to indicate end of client requests.\n* PacketConnection.startup_shutdown: send ERQ_Packet at stream shutdown.\n* New PacketConnection.end_requests() method to queue an ERQ_Packet to the send queue.\n* PacketConnection: send the EOF_Packet from the send worker instead of from startup_shutdown.\n* Rename PacketConnection.do to PacketConnection.__call__.\n* PacketStream: BREAKING: replace the recv and send parameters with a singe recv_send parameter.\n* PacketStream: do not close supplied connection handles - this allows reuse of an underlying binary connection.\n* Many many logic fixes for clean and orderly shutdown.\n* Rename PacketConnection.request to PacketConnection.submit.\n* New BaseRequest and HasPacketConnection helper classes to make it easy to use a PacketConnection for a protocol.\n\n## Class `BaseRequest(cs.binary.AbstractBinary)`\n\nA base class for request classes to use with `HasPacketConnection`.\n\nThis is a mixin aimed at `*Binary` classes representing the\nrequest payload and supplies an `__init__` method which saves\nthe optional `flags` parameter as `.flags` and passes all\nother parameters to the superclass' `__init__`\n(the `*Binary` superclass).\n\nAs such, it is important to define the subclass like this:\n\n    class AddRequest(\n        BaseRequest,\n        BinaryMultiValue('AddRequest', dict(hashenum=BSUInt, data=BSData)),\n    ):\n\nwith `BaseRequest` _first_ if you wish to omit an `__init__` method.\n\nSubclasses must implement the `fulfil` method to perform the\nrequest operation.\n\nOften a subclass will also implement the\n`decode_response_payload(flags,payload)` method.\nThis provides the result of a request, returned by\n`HasPacketConnection.conn_do_remote` or by the `Result`\nreturned from `HasPacketConnection.conn_submit`.\nThe default returns the response `flags` and `payload` directly.\n\nThis base class subclasses `AbstractBinary` to encode and\ndecode the request `payload` and has an additions `flags`\nattribute for the `Packet.flags`.  As such, subclasses have\ntwo main routes for implemetation:\n\n1: Subclass an existing `AbstractBinary` subclass. For example,\n   the `cs.vt.stream.ContainsRequest` looks up a hash code, and\n   subclasses the `cs.vt.hash.HashField` class.\n\n2: Provide a `parse(bfr)` factory method and `transcribe()`\n   method to parse and transcribe the request `payload` like any\n   other `AbstractBinary` subclass.\n\nApproach 1 does not necessarily need a distinct class;\na binary class can often be constructed in the class header.\nFor example, the `cs.vt.stream.AddRequest` payload is an `int`\nrepresenting the hash class and the data to add. The class\nheader looks like this:\n\n    class AddRequest(\n        BaseRequest,\n        BinaryMultiValue('AddRequest', dict(hashenum=BSUInt, data=BSData)),\n    ):\n\nmuch as one might subclass a `namedtuple` in other circumstances.\n\n*Method `BaseRequest.decode_response_payload(self, flags: int, payload: bytes)`*:\nDecode a _response_ `flags` and `payload`.\n\nThis default implementation returns the `flags` and `payload` unchanged.\n\n*Method `BaseRequest.from_request_payload(flags: int, payload: bytes) -> 'BaseRequest'`*:\nDecode a _request_ `flags` and `payload`, return a `BaseRequest` instance.\n\nThis is called with the correct `BaseRequest` subclass\nderived from the received `Packet.rq_type`.\nIt decodes the \n\nThis default implementation assumes that `flags==0`\nand calls `cls.from_bytes(payload)`.\n\n*Method `BaseRequest.fulfil(self, context) -> Union[NoneType, int, bytes, str, Tuple[int, bytes]]`*:\nFulfil this request at the receiving end of the connection using\n`context`, some outer object using the connection.\nRaise an exception if the request cannot be fulfilled.\n\nReturn values suitable for the response:\n* `None`: equivalent to `(0,b'')`\n* `int`: returned in the flags with `b''` for the payload\n* `bytes`: returned as the payload with `0` as the flags\n* `str`: return `encode(s,'ascii')` as the payload with `0` as the flags\n* `(int,bytes)`: the flags and payload\n\nA typical implementation looks like this:\n\n    def fulfil(self, context):\n        return context.come_method(params...)\n\nwhere `params` come from the request attributes.\n\n## Class `HasPacketConnection`\n\nThis is a mixin class to aid writing classes which use a\n`PacketConnection` to communicate with some service.\n\nThe supported request/response packet types are provided as\na mapping of `int` `Packet.rq_type` values to a class\nimplementing that request type, a subclass of `BaseRequest`.\n\nFor example, a `cs.vt.stream.StreamStore` subclasses `HasPacketConnection`\nand initialises the mixin with this call:\n\n    HasPacketConnection.__init__(\n        self,\n        recv_send,\n        name,\n        { 0: AddRequest,  # add chunk, return hashcode\n          1: GetRequest,  # get chunk from hashcode\n          .......\n        },\n    )\n\nSee the `BaseRequest` class for details on how to implement\neach request type.\n\n*Method `HasPacketConnection.__init__(self, recv_send: Union[Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile]], Callable[[], Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile], Callable[[], NoneType]]]], name: str = None, *, rq_type_map: Mapping[int, cs.packetstream.BaseRequest], **packet_kw)`*:\nInitialise `self.conn` as a `PacketConnection`.\n\nParameters:\n* `recv_send`: as for `PacketConnection`\n* `name`: an optional name for the connection\n* `rq_type_map`: a mapping of request types to `BaseRequest` subclasses\n\nOther keyword arguments are passed to `PacketConnection()`.\n\n*Method `HasPacketConnection.conn_do_remote(self, rq: cs.packetstream.BaseRequest, **submit_kw)`*:\nRun `rq` remotely.\nRaises `ValueError` if the response is not ok.\nOtherwise returns `rq.decode_response(flags, payload)`.\n\n*Method `HasPacketConnection.conn_handle_request(self, rq_type: int, flags: int, payload: bytes)`*:\nHandle receipt of a request packet.\nDecode the packet into a request `rq` and return `rq.fulfil(self)`.\n\n*Method `HasPacketConnection.conn_submit(self, rq: cs.packetstream.BaseRequest, *, channel=0, label=None) -> cs.result.Result`*:\nSubmit this request to the connection, return a `Result`.\n\n## Class `Packet(cs.binary.SimpleBinary)`\n\nA protocol packet.\n\n*Method `Packet.__str__(self)`*:\npylint: disable=signature-differs\n\n*Method `Packet.parse(bfr, log=None)`*:\nParse a `Packet` from a buffer.\n\n*Method `Packet.transcribe(self)`*:\nTranscribe this packet.\n\n*Method `Packet.write(self, file, flush=False, log=None)`*:\nWrite the `Packet` to `file`.\n\n## Class `PacketConnection(cs.resources.MultiOpenMixin)`\n\nA bidirectional binary connection for exchanging requests and responses.\n\n*Method `PacketConnection.__init__(self, recv_send: Union[Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile]], Callable[[], Tuple[Union[int, cs.packetstream.ReadableFile, cs.buffer.CornuCopyBuffer], Union[int, cs.packetstream.SendableFile], Callable[[], NoneType]]]], name=None, *, request_handler=None, packet_grace=None, trace_log: Optional[Callable] = None)`*:\nInitialise the `PacketConnection`.\n\nParameters:\n* `recv_send`: specify the receive and send streams\n* `packet_grace`:\n  default pause in the packet sending worker\n  to allow another packet to be queued\n  before flushing the output stream.\n  Default: `DEFAULT_PACKET_GRACE`s.\n  A value of `0` will flush immediately if the queue is empty.\n* `request_handler`: an optional callable accepting\n  (`rq_type`, `flags`, `payload`).\n  The request_handler may return one of 5 values on success:\n  * `None`: response will be 0 flags and an empty payload.\n  * `int`: flags only. Response will be the flags and an empty payload.\n  * `bytes`: payload only. Response will be 0 flags and the payload.\n  * `str`: payload only. Response will be 0 flags and the str\n          encoded as bytes using UTF-8.\n  * `(int, bytes)`: Specify flags and payload for response.\n  An unsuccessful request should raise an exception, which\n  will cause a failure response packet.\n\nThe `recv_send` parameter is used to prepare the connection.\nIt may take the following forms:\n* a 2-tuple of `(recv,send)` specifying the receive and send streams\n* an `int` specifying a single file descriptor used for\n  both receive and send\n* a callable returning a 3-tuple of `(recv,send,close)` as\n  for `PacketConnection`'s callable mode\nThe `(recv,send)` pair indicate the inbound and outbound binary streams.\n\nFor preexisting streams such as pipes or sockets these can be:\n* `recv`: anything acceptable to `CornuCopyBuffer.promote()`,\n  typically a file descriptor or a binary file with `.write`\n  and `.flush` methods.\n* `send`: a file descriptor or a binary file with `.write`\n  and `.flush` methods.\n\nFor \"on demand\" use, `recv` may be a callable and `send` may be `None`.\nIn this case, `recv()` must return a 3-tuple of\n`(recv,send,shutdown)` being values for `recv` and `send`\nas above, and a shutdown function to do the necessary \"close\"\nof the new `recv` and `send`. `shutdown` may be `None` if there is\nno meaningful close operation.\nThe `PacketConnection`'s `startup_shutdown` method will\ncall `recv()` to obtain the binary streams and call the\n`shutdown` on completion.\nThis supports use for on demand connections, eg:\n\n    P = PacketConnection(connect_to_server)\n    ......\n    with P:\n        ... use P to to work ...\n\nwhere `connect_to_server()` might connect to some remote service.\n\n*Method `PacketConnection.__call__(self, rq_type, payload=b'', flags=0, *, decode_response=None, channel=0, label=None)`*:\nCalling the `PacketConnection` performs a synchronous request.\nSubmits the request, then calls the `Result` returned from the request.\n\n*Method `PacketConnection.join(self)`*:\nWait for the send and receive workers to terminate.\n\n*Method `PacketConnection.join_recv(self)`*:\nWait for the end of the receive worker.\nServers should call this.\n\n*Method `PacketConnection.send_eof(self)`*:\nQueue the magic EOF `Packet`.\n\n*Method `PacketConnection.send_erq(self)`*:\nQueue the magic end-of-requests `Packet`.\n\n*Method `PacketConnection.submit(self, rq_type: int, flags: int = 0, payload: bytes = b'', *, decode_response=None, channel=0, label=None) -> cs.result.Result`*:\nCompose and dispatch a new request, returns a `Result`.\n\nAllocates a new tag, a `Result` to deliver the response, and\nrecords the response decode function for use when the\nresponse arrives.\n\nParameters:\n* `rq_type`: request type code, an `int`\n* `flags`: optional flags to accompany the request, an int;\n  default `0`.\n* `payload`: optional bytes-like object to accompany the request;\n  default `b''`\n* `decode_response`: optional callable accepting (response_flags,\n  response_payload_bytes) and returning the decoded response payload\n  value; if unspecified, the response payload bytes are used\n* `label`: optional label for this request to aid debugging\n\nThe `Result` will yield an `(ok, flags, payload)` tuple, where:\n* `ok`: whether the request was successful\n* `flags`: the response flags\n* `payload`: the response payload, decoded by decode_response\n  if specified\n\n## Class `ReadableFile(typing.Protocol)`\n\nThe requirements for a file used to receive.\n\n*Method `ReadableFile.__subclasshook__(other)`*:\nSet (or override) the protocol subclass hook.\n\n*Method `ReadableFile.read(self, size: int) -> bytes`*:\nRead up to `size` bytes.\n\n## Class `RequestState(RequestState)`\n\nA state object tracking a particular request.\n\n*Method `RequestState.cancel(self)`*:\nCancel this request.\n\n*Method `RequestState.complete(self, flags, payload)`*:\nComplete the request from an \"ok\" `flags` and `payload`.\n\n*Method `RequestState.fail(self, flags, payload)`*:\nFail the request from a \"not ok\" `flags` and `payload`.\n\n## Class `SendableFile(typing.Protocol)`\n\nThe requirements for a file used to send.\n\n*Method `SendableFile.__subclasshook__(other)`*:\nSet (or override) the protocol subclass hook.\n\n*Method `SendableFile.flush(self) -> None`*:\nFlush any buffer of written bytes.\n\n*Method `SendableFile.write(self, bs: bytes) -> int`*:\nWrite bytes, return the number of bytes written.\n\n# Release Log\n\n\n\n*Release 20240630*:\n* New ERQ_Packet to indicate end of client requests.\n* PacketConnection.startup_shutdown: send ERQ_Packet at stream shutdown.\n* New PacketConnection.end_requests() method to queue an ERQ_Packet to the send queue.\n* PacketConnection: send the EOF_Packet from the send worker instead of from startup_shutdown.\n* Rename PacketConnection.do to PacketConnection.__call__.\n* PacketStream: BREAKING: replace the recv and send parameters with a singe recv_send parameter.\n* PacketStream: do not close supplied connection handles - this allows reuse of an underlying binary connection.\n* Many many logic fixes for clean and orderly shutdown.\n* Rename PacketConnection.request to PacketConnection.submit.\n* New BaseRequest and HasPacketConnection helper classes to make it easy to use a PacketConnection for a protocol.\n\n*Release 20240412*:\n* PacketConnection: now subclasses MultiOpenMixin, big refactor.\n* PacketConnection.__init__: use @promote to turn the recv parameter into a CornuCopyBuffer.\n* Fix a deadlock.\n\n*Release 20211208*:\n* Packet.__eq__: only test .rq_type if .is_request.\n* Update tests for changes.\n\n*Release 20210306*:\n* Port to new cs.binary.Binary* classes.\n* Some refactors and small fixes.\n\n*Release 20191004*:\n* PacketConnection: new optional parameter `packet_grace` to tune the send delay for additional packets before a flush, default DEFAULT_PACKET_GRACE (0.01s), 0 for no delay.\n* Add a crude packet level activity ticker.\n\n*Release 20190221*:\nDISTINFO requirement updates.\n\n*Release 20181228*:\nInitial PyPI release.\n",
    "bugtrack_url": null,
    "license": "GNU General Public License v3 or later (GPLv3+)",
    "summary": "general purpose bidirectional packet stream connection",
    "version": "20240630",
    "project_urls": {
        "MonoRepo Commits": "https://bitbucket.org/cameron_simpson/css/commits/branch/main",
        "Monorepo Git Mirror": "https://github.com/cameron-simpson/css",
        "Monorepo Hg/Mercurial Mirror": "https://hg.sr.ht/~cameron-simpson/css",
        "Source": "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/packetstream.py"
    },
    "split_keywords": [
        "python2",
        " python3"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1a850a4cc48ea1b718a93c4e9360204101f4d84161f32af77a8118db07990ee3",
                "md5": "ea1d37caf19e02491947a5f8882ea2a2",
                "sha256": "e3ffdc59a038299379af673b66ea81a9acfc9fbc12735b8c4460afd430e41c2c"
            },
            "downloads": -1,
            "filename": "cs.packetstream-20240630-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ea1d37caf19e02491947a5f8882ea2a2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 17287,
            "upload_time": "2024-06-30T02:06:09",
            "upload_time_iso_8601": "2024-06-30T02:06:09.868483Z",
            "url": "https://files.pythonhosted.org/packages/1a/85/0a4cc48ea1b718a93c4e9360204101f4d84161f32af77a8118db07990ee3/cs.packetstream-20240630-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "31da6252b713fa3efa66539e259d7e9df3a886c21bd10709808d14736dbca236",
                "md5": "87c20ffb7f9adb289faba93c73bcaff8",
                "sha256": "a95886bc3d1e28ddd58c9ff62429dfc54dc73dc7eb87a7b60cb3745cadb3566c"
            },
            "downloads": -1,
            "filename": "cs.packetstream-20240630.tar.gz",
            "has_sig": false,
            "md5_digest": "87c20ffb7f9adb289faba93c73bcaff8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 19721,
            "upload_time": "2024-06-30T02:06:11",
            "upload_time_iso_8601": "2024-06-30T02:06:11.751901Z",
            "url": "https://files.pythonhosted.org/packages/31/da/6252b713fa3efa66539e259d7e9df3a886c21bd10709808d14736dbca236/cs.packetstream-20240630.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-06-30 02:06:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "cameron-simpson",
    "github_project": "css",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "cs.packetstream"
}
        
Elapsed time: 4.65225s