class Channel(object): COMPRESSION_THRESHOLD = 3000 COMPRESSION_LEVEL = 1 FRAME_HEADER = Struct("!LB") FLUSHER = "\n" # cause any line-buffered layers below us to flush __slots__ = ["stream", "compress"] def __init__(self, stream, compress=True): self.stream = stream if not zlib: compress = False self.compress = compress def close(self): self.stream.close() @property def closed(self): return self.stream.closed def fileno(self): return self.stream.fileno() def poll(self, timeout): return self.stream.poll(timeout) def recv(self): header = self.stream.read(self.FRAME_HEADER.size) length, compressed = self.FRAME_HEADER.unpack(header) data = self.stream.read(length + len(self.FLUSHER))[:-len(self.FLUSHER)] if compressed: data = zlib.decompress(data) return data def send(self, data): if self.compress and len(data) > self.COMPRESSION_THRESHOLD: compressed = 1 data = zlib.compress(data, self.COMPRESSION_LEVEL) else: compressed = 0 header = self.FRAME_HEADER.pack(len(data), compressed) buf = header + data + self.FLUSHER self.stream.write(buf)
class Channel(object): """Channel implementation. Note: In order to avoid problems with all sorts of line-buffered transports, we deliberately add ``\\n`` at the end of each frame. """ COMPRESSION_THRESHOLD = 3000 COMPRESSION_LEVEL = 1 FRAME_HEADER = Struct("!LB") FLUSHER = BYTES_LITERAL( "\n") # cause any line-buffered layers below us to flush __slots__ = ["stream", "compress"] def __init__(self, stream, compress=True): self.stream = stream if not zlib: compress = False self.compress = compress def close(self): """closes the channel and underlying stream""" self.stream.close() @property def closed(self): """indicates whether the underlying stream has been closed""" return self.stream.closed def fileno(self): """returns the file descriptor of the underlying stream""" return self.stream.fileno() def poll(self, timeout): """polls the underlying steam for data, waiting up to *timeout* seconds""" return self.stream.poll(timeout) def recv(self): """Receives the next packet (or *frame*) from the underlying stream. This method will block until the packet has been read completely :returns: string of data """ header = self.stream.read(self.FRAME_HEADER.size) length, compressed = self.FRAME_HEADER.unpack(header) data = self.stream.read(length + len(self.FLUSHER))[:-len(self.FLUSHER)] if compressed: data = zlib.decompress(data) return data def send(self, data): """Sends the given string of data as a packet over the underlying stream. Blocks until the packet has been sent. :param data: the byte string to send as a packet """ if self.compress and len(data) > self.COMPRESSION_THRESHOLD: compressed = 1 data = zlib.compress(data, self.COMPRESSION_LEVEL) else: compressed = 0 header = self.FRAME_HEADER.pack(len(data), compressed) buf = header + data + self.FLUSHER self.stream.write(buf)
TAG_STR_L4 = b"\x0f" TAG_TUP1 = b"\x10" TAG_TUP2 = b"\x11" TAG_TUP3 = b"\x12" TAG_TUP4 = b"\x13" TAG_TUP_L1 = b"\x14" TAG_TUP_L4 = b"\x15" TAG_INT_L1 = b"\x16" TAG_INT_L4 = b"\x17" TAG_FLOAT = b"\x18" TAG_SLICE = b"\x19" TAG_FSET = b"\x1a" TAG_COMPLEX = b"\x1b" IMM_INTS = dict((i, bytes([i + 0x50])) for i in range(-0x30, 0xa0)) I1 = Struct("!B") I4 = Struct("!L") F8 = Struct("!d") C16 = Struct("!dd") _dump_registry = {} _load_registry = {} IMM_INTS_LOADER = dict((v, k) for k, v in IMM_INTS.items()) def register(coll, key): def deco(func): coll[key] = func return func return deco