Facilities associated with binary data parsing and transcription. The classes in this module support easy parsing of binary data structures, returning instances with the binary data decoded into attributes and capable of transcribing themselves in binary form (trivially via `bytes(instance)` and also otherwise).
Project description
Facilities associated with binary data parsing and transcription.
The classes in this module support easy parsing of binary data
structures,
returning instances with the binary data decoded into attributes
and capable of transcribing themselves in binary form
(trivially via bytes(instance) and also otherwise).
Latest release 20250501:
- @binclass: a dataclass-like way to specify binary structures.
- Rename BinaryByteses to BinaryBytes.
- Rename BinaryMultiStruct and BinarySingleStruct to BinaryStruct.
- New bs(bytes) subclass with a compact repr().
- BinarySingleValue classes now expect a type specification for the value.
- BinarySingleValue now subclasses cs.deco.Promotable.
- New struct_field_types(struct_format,field_names) to return a mapping of field names to struct.unpack-returned types.
- New is_single_value(obj) to test for single value binary objects.
- New ListOfBinary, a class holding a list of instances of some binary class.
- Many internal updates and improvements.
See cs.iso14496 for an ISO 14496 (eg MPEG4) parser
built using this module.
Note: this module requires Python 3.6+ because various default
behaviours rely on dicts preserving their insert order.
Terminology used below:
- buffer:
an instance of
cs.buffer.CornuCopyBuffer, which manages an iterable of bytes-like values and has various useful methods for parsing. - chunk:
a piece of binary data obeying the buffer protocol,
i.e. a
collections.abc.Buffer; almost always abytesinstance or amemoryview, but in principle also things likebytearray.
The CornuCopyBuffer is the basis for all parsing, as it manages
a variety of input sources such as files, memory, sockets etc.
It also has a factory methods to make one from a variety of sources
such as bytes, iterables, binary files, mmapped files,
TCP data streams, etc.
All the binary classes subclass AbstractBinary,
Amongst other things, this means that the binary transcription
can be had simply from bytes(instance),
although there are more transcription methods provided
for when greater flexibility is desired.
It also means that all classes have parse* and scan* methods
for parsing binary data streams.
The .parse(cls,bfr) class method reads binary data from a
buffer and returns an instance.
The .transcribe(self) method may be a regular function or a
generator which returns or yields things which can be transcribed
as bytes via the flatten function.
See the AbstractBinary.transcribe docstring for specifics; this might:
- return a
bytes - return an ASCII string
- be a generator which yields various values such as bytes,
ASCII strings, other
AbstractBinaryinstances such as each field (which get transcribed in turn) or an iterable of these things
There are 6 main ways an implementor might base their data structures:
BinaryStruct: a factory for classes based on astruct.structformat string with multiple values; this also builds anamedtuplesubclass@binclass: a dataclass-like specification of a binary structureBinarySingleValue: a base class for subclasses parsing and transcribing a single value, such asUInt8orBinaryUTF8NULBinaryMultiValue: a factory for subclasses parsing and transcribing multiple values with no variationSimpleBinary: a base class for subclasses with custom.parseand.transcribemethods, for structures with variable fields; this makes aSimpleNamespacesubclass
These can all be mixed as appropriate to your needs.
You can also instantiate objects directly; there's no requirement for the source information to be binary.
There are several presupplied subclasses for common basic types
such as UInt32BE (an unsigned 32 bit big endian integer).
Some Examples
A BinaryStruct, from cs.iso14496
A simple struct style definitiion for 9 longs:
Matrix9Long = BinaryStruct(
'Matrix9Long', '>lllllllll', 'v0 v1 v2 v3 v4 v5 v6 v7 v8'
)
Per the struct.struct format string, this parses 9 big endian longs
and returns a namedtuple with 9 fields.
Like all the AbstractBinary subclasses, parsing an instance from a
stream can be done like this:
m9 = Matrix9Long.parse(bfr)
print("m9.v3", m9.v3)
and writing its binary form to a file like this:
f.write(bytes(m9))
A @binclass, also from cs.iso14496
For reasons to do with the larger MP4 parser this uses an extra
decorator @boxbodyclass which is just a shim for the @binclass
decorator with an addition step.
@boxbodyclass
class FullBoxBody2(BoxBody):
""" A common extension of a basic `BoxBody`, with a version and flags field.
ISO14496 section 4.2.
"""
version: UInt8
flags0: UInt8
flags1: UInt8
flags2: UInt8
@property
def flags(self):
""" The flags value, computed from the 3 flag bytes.
"""
return (self.flags0 << 16) | (self.flags1 << 8) | self.flags2
This has 4 fields, each an unsigned 8 bit value (one bytes),
and a property .flags which is the overall flags value for
the box header.
You should look at the source code for the TKHDBoxBody from
that module for an example of a @binclass with a variable
collection of fields based on an earlier version field value.
A BinarySingleValue, the BSUInt from thos module
The BSUint transcribes an unsigned integera of arbitrary size
as a big endian variable sizes sequence of bytes.
I understand this is the same scheme MIDI uses.
You can define a BinarySingleValue with conventional .parse()
and .transribe() methods but it is usually expedient to instead
provide .parse_value() and transcribe_value() methods, which
return or transcibe the core value (the unsigned integer in
this case).
class BSUInt(BinarySingleValue, value_type=int):
""" A binary serialised unsigned `int`.
This uses a big endian byte encoding where continuation octets
have their high bit set. The bits contributing to the value
are in the low order 7 bits.
"""
@staticmethod
def parse_value(bfr: CornuCopyBuffer) -> int:
""" Parse an extensible byte serialised unsigned `int` from a buffer.
Continuation octets have their high bit set.
The value is big-endian.
This is the go for reading from a stream. If you already have
a bare bytes instance then the `.decode_bytes` static method
is probably most efficient;
there is of course the usual `AbstractBinary.parse_bytes`
but that constructs a buffer to obtain the individual bytes.
"""
n = 0
b = 0x80
while b & 0x80:
b = bfr.byte0()
n = (n << 7) | (b & 0x7f)
return n
# pylint: disable=arguments-renamed
@staticmethod
def transcribe_value(n):
""" Encode an unsigned int as an entensible byte serialised octet
sequence for decode. Return the bytes object.
"""
bs = [n & 0x7f]
n >>= 7
while n > 0:
bs.append(0x80 | (n & 0x7f))
n >>= 7
return bytes(reversed(bs))
A BinaryMultiValue
A BinaryMultiValue s a class factory for making a multi field
AbstractBinary from variable field descriptions.
You're probably better off using @binclass these days.
See the BinaryMutliValue docstring for details and an example.
An MP4 ELST box:
class ELSTBoxBody(FullBoxBody):
""" An 'elst' Edit List FullBoxBody - section 8.6.6.
"""
V0EditEntry = BinaryStruct(
'ELSTBoxBody_V0EditEntry', '>Llhh',
'segment_duration media_time media_rate_integer media_rate_fraction'
)
V1EditEntry = BinaryStruct(
'ELSTBoxBody_V1EditEntry', '>Qqhh',
'segment_duration media_time media_rate_integer media_rate_fraction'
)
@property
def entry_class(self):
""" The class representing each entry.
"""
return self.V1EditEntry if self.version == 1 else self.V0EditEntry
@property
def entry_count(self):
""" The number of entries.
"""
return len(self.entries)
def parse_fields(self, bfr: CornuCopyBuffer):
""" Parse the fields of an `ELSTBoxBody`.
"""
super().parse_fields(bfr)
assert self.version in (0, 1)
entry_count = UInt32BE.parse_value(bfr)
self.entries = list(self.entry_class.scan(bfr, count=entry_count))
def transcribe(self):
""" Transcribe an `ELSTBoxBody`.
"""
yield super().transcribe()
yield UInt32BE.transcribe_value(self.entry_count)
yield map(self.entry_class.transcribe, self.entries)
A Edit List box comes in a version 0 and version 1 form, differing
in the field sizes in the edit entries. This defines two
flavours of edit entry structure and a property to return the
suitable class based on the version field. The parse_fields()
method is called from the base BoxBody class' parse() method
to collect addition fields for any box. For this box it collectsa
32 bit entry_count and then a list of that many edit entries.
The transcription yields corresponding values.
Short summary:
AbstractBinary: Abstract class for allBinary* implementations, specifying the abstractparseandtranscribemethods and providing various helper methods.BinaryBytes: A list ofbytesparsed directly from the native iteration of the buffer. Subclasses are initialised with aconsume=class parameter indicating how many bytes to console on parse; the default is...meaning to consume the entire remaining buffer, but a positive integer can also be supplied to consume exactly that many bytes.BinaryFixedBytes: Factory for anAbstractBinarysubclass matchinglengthbytes of data. The bytes are saved as the attribute.data.BinaryListValues: A list of values with a common parse specification, such as sample or Boxes in an ISO14496 Box structure.BinaryMultiStruct: A class factory forAbstractBinarynamedtuplesubclasses built around potentially complexstructformats.BinaryMultiValue: Construct aSimpleBinarysubclass namedclass_namewhose fields are specified by the mappingfield_map.BinarySingleStruct: OBSOLETE BinaryStruct.BinarySingleValue: A representation of a single value as the attribute.value.BinaryStruct: OBSOLETE BinaryStruct.BinaryUTF16NUL: A NUL terminated UTF-16 string.BinaryUTF8NUL: A NUL terminated UTF-8 string.binclass: A decorator fordataclass-like binary classes.bs: Abytes subclass with a compactrepr()`.BSData: A run length encoded data chunk, with the length encoded as aBSUInt.BSSFloat: A float transcribed as aBSStringofstr(float).BSString: A run length encoded string, with the length encoded as a BSUInt.BSUInt: A binary serialised unsignedint.flatten: Flattentranscriptioninto an iterable ofBuffers. None of theBuffers will be empty.Float64BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>d'and presents the attributes ['value'].Float64LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<d'and presents the attributes ['value'].Int16BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>h'and presents the attributes ['value'].Int16LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<h'and presents the attributes ['value'].Int32BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>l'and presents the attributes ['value'].Int32LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<l'and presents the attributes ['value'].is_single_value: Test whetherobjis a single value binary object.parse_offsets: Decorateparse(usually anAbstractBinaryclass method) to record the buffer starting offset asself.offsetand the buffer post parse offset asself.end_offset. If the decorator parameterreportis true, callbfr.report_offset()with the starting offset at the end of the parse.pt_spec: Convert a parse/transcribe specificationptinto anAbstractBinarysubclass.SimpleBinary: Abstract binary class based on aSimpleNamespace, thus providing a nice__str__and a keyword based__init__. Implementors must still define.parseand.transcribe.struct_field_types: Construct adictmapping field names to struct return types.UInt16BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>H'and presents the attributes ['value'].UInt16LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<H'and presents the attributes ['value'].UInt32BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>L'and presents the attributes ['value'].UInt32LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<L'and presents the attributes ['value'].UInt64BE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>Q'and presents the attributes ['value'].UInt64LE: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<Q'and presents the attributes ['value'].UInt8: AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'B'and presents the attributes ['value'].
Module contents:
-
ClassAbstractBinary(cs.deco.Promotable): Abstract class for allBinary* implementations, specifying the abstractparseandtranscribe` methods and providing various helper methods.Naming conventions:
parse* methods parse a single instance from a bufferscan* methods are generators yielding successive instances from a buffer
AbstractBinary.__bytes__(self):
The binary transcription as a single bytes object.
AbstractBinary.__len__(self):
Compute the length by running a transcription and measuring it.
AbstractBinary.__str__(self, attr_names=None, attr_choose=None, str_func=None):
The string summary of this object.
If called explicitly rather than via str() the following
optional parametsrs may be supplied:
attr_names: an iterable ofstrnaming the attributes to include; the default if the keys ofself.__dict__attr_choose: a callable to select amongst the attribute names names; the default is to choose names which do not start with an underscorestr_func: a callable returning the string form of an attribute value; the default returnscropped_repr(v)wherevis the value's.valueattribute for single value objects otherwise the object itself
AbstractBinary.from_bytes(bs, **parse_bytes_kw):
Factory to parse an instance from the
bytes bs starting at offset.
Returns the new instance.
Raises ValueError if bs is not entirely consumed.
Raises EOFError if bs has insufficient data.
Keyword parameters are passed to the .parse_bytes method.
This relies on the cls.parse method for the parse.
AbstractBinary.load(f):
Load an instance from the file f
which may be a filename or an open file as for AbstractBinary.scan.
Return the instance or None if the file is empty.
AbstractBinary.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse an instance of cls from the buffer bfr.
AbstractBinary.parse_bytes(bs, offset=0, length=None, **parse_kw):
Factory to parse an instance from the
bytes bs starting at offset.
Returns (instance,offset) being the new instance and the post offset.
Raises EOFError if bs has insufficient data.
The parameters offset and length are passed to the
CornuCopyBuffer.from_bytes factory.
Other keyword parameters are passed to the .parse method.
This relies on the cls.parse method for the parse.
AbstractBinary.save(self, f):
Save this instance to the file f
which may be a filename or an open file.
Return the length of the transcription.
AbstractBinary.scan(bfr: cs.buffer.CornuCopyBuffer, count=None, *, min_count=None, max_count=None, with_offsets=False, **parse_kw):
A generator to scan the buffer bfr for repeated instances of cls
until end of input, and yield them.
Note that if bfr is not already a CornuCopyBuffer
it is promoted to CornuCopyBuffer from several types
such as filenames etc; see CornuCopyBuffer.promote.
Parameters:
bfr: the buffer to scan, or any object suitable forCornuCopyBuffer.promotecount: the required number of instances to scan, equivalent to settingmin_count=countandmax_count=countmin_count: the minimum number of instances to scanmax_count: the maximum number of instances to scanwith_offsets: optional flag, defaultFalse; if true yield(pre_offset,obj,post_offset), otherwise justobjIt is in error to specify bothcountand one ofmin_countormax_count.
Other keyword arguments are passed to self.parse().
Scanning stops after max_count instances (if specified).
If fewer than min_count instances (if specified) are scanned
a warning is issued.
This is to accomodate nonconformant streams without raising exceptions.
Callers wanting to validate max_count may want to probe bfr.at_eof()
after return.
Callers not wanting a warning over min_count should not specify it,
and instead check the number of instances returned themselves.
AbstractBinary.scan_fspath(fspath: str, *, with_offsets=False, **kw):
Open the file with filesystenm path fspath for read
and yield from self.scan(..,**kw) or
self.scan_with_offsets(..,**kw) according to the
with_offsets parameter.
Deprecated; please just call scan with a filesystem pathname.
Parameters:
fspath: the filesystem path of the file to scanwith_offsets: optional flag, defaultFalse; if true then scan withscan_with_offsetsinstead of withscanOther keyword parameters are passed toscanorscan_with_offsets.
AbstractBinary.scan_with_offsets(bfr: cs.buffer.CornuCopyBuffer, count=None, min_count=None, max_count=None):
Wrapper for scan() which yields (pre_offset,instance,post_offset)
indicating the start and end offsets of the yielded instances.
All parameters are as for scan().
*Deprecated; please just call scan with the with_offsets=True parameter.
AbstractBinary.self_check(self, *, field_types=None):
Internal self check. Returns True if passed.
If the structure has a FIELD_TYPES attribute, normally a
class attribute, then check the fields against it.
The FIELD_TYPES attribute is a mapping of field_name to
a specification of required and types. The specification
may take one of 2 forms:
- a tuple of
(required,types) - a single
type; this is equivalent to(True,(type,))Their meanings are as follows: required: a Boolean. If true, the field must be present in the packetfield_map, otherwise it need not be present.types: a tuple of acceptable field types
There are some special semantics involved here.
An implementation of a structure may choose to make some
fields plain instance attributes instead of binary objects
in the field_map mapping, particularly variable structures
such as a cs.iso14496.BoxHeader, whose .length may be parsed
directly from its binary form or computed from other fields
depending on the box_size value. Therefore, checking for
a field is first done via the field_map mapping, then by
getattr, and as such the acceptable types may include
nonstructure types such as int.
Here is the cs.iso14496 Box.FIELD_TYPES definition as an example:
FIELD_TYPES = {
'header': BoxHeader,
'body': BoxBody,
'unparsed': list,
'offset': int,
'unparsed_offset': int,
'end_offset': int,
}
Note that length includes some nonstructure types,
and that it is written as a tuple of (True,types) because
it has more than one acceptable type.
AbstractBinary.transcribe(self):
Return or yield bytes, ASCII string, None or iterables
comprising the binary form of this instance.
This aims for maximum convenience when transcribing a data structure.
This may be implemented as a generator, yielding parts of the structure.
This may be implemented as a normal function, returning:
None: no bytes of data, for example for an omitted or empty structure- a
bytes-like object: the full data bytes for the structure - an ASCII compatible string:
this will be encoded with the
'ascii'encoding to makebytes - an iterable:
the components of the structure,
including substranscriptions which themselves
adhere to this protocol - they may be
None,bytes-like objects, ASCII compatible strings or iterables. This supports directly returning or yielding the result of a field's.transcribemethod.
AbstractBinary.transcribe_flat(self):
Return a flat iterable of chunks transcribing this field.
AbstractBinary.transcribed_length(self):
Compute the length by running a transcription and measuring it.
AbstractBinary.write(self, file, *, flush=False):
Write this instance to file, a file-like object supporting
.write(bytes) and .flush().
Return the number of bytes written.
ClassBinaryBytes(BinarySingleValue): A list ofbytesparsed directly from the native iteration of the buffer. Subclasses are initialised with aconsume=class parameter indicating how many bytes to console on parse; the default is...` meaning to consume the entire remaining buffer, but a positive integer can also be supplied to consume exactly that many bytes.
BinaryBytes.parse(bfr: cs.buffer.CornuCopyBuffer):
Consume cls.PARSE_SIZE bytes from the buffer and instantiate a new instance.
BinaryBytes.promote(obj):
Promote obj to a BinaryBytes instance.
Other instances of AbstractBinary will be transcribed into the buffers.
Otherwise use BinarySingleValue.promote(obj).
BinaryBytes.transcribe(self):
Transcribe each value.
BinaryBytes.value:
The internal list of bytes instances joined together.
This is a property and may be expensive to compute for a large list.
BinaryFixedBytes(class_name: str, length: int): Factory for anAbstractBinarysubclass matchinglengthbytes of data. The bytes are saved as the attribute.data.ClassBinaryListValues(AbstractBinary)`: A list of values with a common parse specification, such as sample or Boxes in an ISO14496 Box structure.
BinaryListValues.parse(bfr: cs.buffer.CornuCopyBuffer, count=None, *, end_offset=None, min_count=None, max_count=None, pt):
Read values from bfr.
Return a BinaryListValue containing the values.
Parameters:
count: optional count of values to read; if specified, exactly this many values are expected.end_offset: an optional bounding end offset of the buffer.min_count: the least acceptable number of values.max_count: the most acceptable number of values.pt: a parse/transcribe specification as accepted by thept_spec()factory. The values will be returned by its parse function.
BinaryListValues.transcribe(self):
Transcribe all the values.
-
BinaryMultiStruct(class_name: str, struct_format: str, field_names: Union[str, List[str]] = 'value'): A class factory forAbstractBinarynamedtuplesubclasses built around potentially complexstructformats.Parameters:
class_name: name for the generated classstruct_format: thestructformat stringfield_names: optional field name list, a space separated string or an interable of strings; the default is'value', intended for single field structs
Example:
# an "access point" record from the .ap file Enigma2APInfo = BinaryStruct('Enigma2APInfo', '>QQ', 'pts offset') # a "cut" record from the .cuts file Enigma2Cut = BinaryStruct('Enigma2Cut', '>QL', 'pts type') >>> UInt16BE = BinaryStruct('UInt16BE', '>H') >>> UInt16BE.__name__ 'UInt16BE' >>> UInt16BE.format '>H' >>> UInt16BE.struct #doctest: +ELLIPSIS <_struct.Struct object at ...> >>> field = UInt16BE.from_bytes(bytes((2,3))) >>> field UInt16BE('>H',value=515) >>> field.value 515 -
BinaryMultiValue(class_name, field_map, field_order=None): Construct aSimpleBinarysubclass namedclass_namewhose fields are specified by the mappingfield_map.The
field_mapis a mapping of field name to parse/trasncribe specifications suitable forpt_spec(); these are all promoted bypt_specintoAbstractBinarysubclasses.The
field_orderis an optional ordering of the field names; the default comes from the iteration order offield_map.Note for Python <3.6: if
field_orderis not specified it is constructed by iterating overfield_map. Prior to Python 3.6,dicts do not provide a reliable order and should be accompanied by an explicitfield_order. From 3.6 onward adictis enough and its insertion order will dictate the defaultfield_order.For a fixed record structure the default
.parseand.transcribemethods will suffice; they parse or transcribe each field in turn. Subclasses with variable records should override the.parseand.transcribemethods accordingly.If the class has both
parse_valueandtranscribe_valuemethods then the value itself will be directly stored. Otherwise the class it presumed to be more complex subclass ofAbstractBinaryand the instance is stored.Here is an example exhibiting various ways of defining each field:
-
n1: defined with the *_valuemethods ofUInt8, which return or transcribe theintfrom an unsigned 8 bit value; this stores aBinarySingleValuewhose.valueis anint -
n2: defined from theUInt8class, which parses an unsigned 8 bit value; this stores anUInt8instance (also aBinarySingleValuewhole.valueis anint) -
n3: liken2 -
data1: defined with the *_valuemethods ofBSData, which return or transcribe the databytesfrom a run length encoded data chunk; this stores aBinarySingleValuewhose.valueis abytes -
data2: defined from theBSDataclass which parses a run length encoded data chunk; this is aBinarySingleValueso we store itsbytesvalue directly.>>> class BMV(BinaryMultiValue("BMV", { ... 'n1': (UInt8.parse_value, UInt8.transcribe_value), ... 'n2': UInt8, ... 'n3': UInt8, ... 'nd': ('>H4s', 'short bs'), ... 'data1': ( ... BSData.parse_value, ... BSData.transcribe_value, ... ), ... 'data2': BSData, ... })): ... pass >>> BMV.FIELD_ORDER ['n1', 'n2', 'n3', 'nd', 'data1', 'data2'] >>> bmv = BMV.from_bytes(b'\x11\x22\x77\x81\x82zyxw\x02AB\x04DEFG') >>> bmv.n1 #doctest: +ELLIPSIS 17 >>> bmv.n2 34 >>> bmv #doctest: +ELLIPSIS BMV(n1=17, n2=34, n3=119, nd=nd('>H4s',short=33154,bs=b'zyxw'), data1=b'AB', data2=b'DEFG') >>> bmv.nd #doctest: +ELLIPSIS nd('>H4s',short=33154,bs=b'zyxw') >>> bmv.nd.bs b'zyxw' >>> bytes(bmv.nd) b'zyxw' >>> bmv.data1 b'AB' >>> bmv.data2 b'DEFG' >>> bytes(bmv) b'\x11"w\x81\x82zyxw\x02AB\x04DEFG' >>> list(bmv.transcribe_flat()) [b'\x11', b'"', b'w', b'\x81\x82zyxw', b'\x02', b'AB', b'\x04', b'DEFG']
-
-
BinarySingleStruct(class_name: str, struct_format: str, field_names: Union[str, List[str]] = 'value'): OBSOLETE BinaryStructA class factory for
AbstractBinarynamedtuplesubclasses built around potentially complexstructformats.Parameters:
class_name: name for the generated classstruct_format: thestructformat stringfield_names: optional field name list, a space separated string or an interable of strings; the default is'value', intended for single field structs
Example:
# an "access point" record from the .ap file Enigma2APInfo = BinaryStruct('Enigma2APInfo', '>QQ', 'pts offset') # a "cut" record from the .cuts file Enigma2Cut = BinaryStruct('Enigma2Cut', '>QL', 'pts type') >>> UInt16BE = BinaryStruct('UInt16BE', '>H') >>> UInt16BE.__name__ 'UInt16BE' >>> UInt16BE.format '>H' >>> UInt16BE.struct #doctest: +ELLIPSIS <_struct.Struct object at ...> >>> field = UInt16BE.from_bytes(bytes((2,3))) >>> field UInt16BE('>H',value=515) >>> field.value 515 -
ClassBinarySingleValue(AbstractBinary): A representation of a single value as the attribute.value`.Subclasses must implement:
parseorparse_valuetranscribeortranscribe_value
BinarySingleValue.__init__(self, value):
Initialise self with value.
BinarySingleValue.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse an instance from bfr.
Subclasses must implement this method or parse_value.
BinarySingleValue.parse_value(bfr: cs.buffer.CornuCopyBuffer):
Parse a value from bfr based on this class.
Subclasses must implement this method or parse.
BinarySingleValue.parse_value_from_bytes(bs, offset=0, length=None, **kw):
Parse a value from the bytes bs based on this class.
Return (value,offset).
BinarySingleValue.scan_values(bfr: cs.buffer.CornuCopyBuffer, **kw):
Scan bfr, yield values.
BinarySingleValue.transcribe(self):
Transcribe this instance as bytes.
Subclasses must implement this method or transcribe_value.
BinarySingleValue.transcribe_value(value):
Transcribe value as bytes based on this class.
Subclasses must implement this method or transcribe.
BinarySingleValue.value_from_bytes(bs, **from_bytes_kw):
Decode an instance from bs using .from_bytes
and return the .value attribute.
Keyword arguments are passed to cls.from_bytes.
-
BinaryStruct(class_name: str, struct_format: str, field_names: Union[str, List[str]] = 'value'): OBSOLETE BinaryStructOBSOLETE BinaryStruct
A class factory for
AbstractBinarynamedtuplesubclasses built around potentially complexstructformats.Parameters:
class_name: name for the generated classstruct_format: thestructformat stringfield_names: optional field name list, a space separated string or an interable of strings; the default is'value', intended for single field structs
Example:
# an "access point" record from the .ap file Enigma2APInfo = BinaryStruct('Enigma2APInfo', '>QQ', 'pts offset') # a "cut" record from the .cuts file Enigma2Cut = BinaryStruct('Enigma2Cut', '>QL', 'pts type') >>> UInt16BE = BinaryStruct('UInt16BE', '>H') >>> UInt16BE.__name__ 'UInt16BE' >>> UInt16BE.format '>H' >>> UInt16BE.struct #doctest: +ELLIPSIS <_struct.Struct object at ...> >>> field = UInt16BE.from_bytes(bytes((2,3))) >>> field UInt16BE('>H',value=515) >>> field.value 515 -
ClassBinaryUTF16NUL(BinarySingleValue)`: A NUL terminated UTF-16 string.
BinaryUTF16NUL.__init__(self, value: str, *, encoding: str):
pylint: disable=super-init-not-called
BinaryUTF16NUL.VALUE_TYPE
BinaryUTF16NUL.parse(bfr: cs.buffer.CornuCopyBuffer, *, encoding: str):
Parse the encoding and value and construct an instance.
BinaryUTF16NUL.parse_value(bfr: cs.buffer.CornuCopyBuffer, *, encoding: str) -> str:
Read a NUL terminated UTF-16 string from bfr, return a UTF16NULField.
The mandatory parameter encoding specifies the UTF16 encoding to use
('utf_16_be' or 'utf_16_le').
BinaryUTF16NUL.transcribe(self):
Transcribe self.value in UTF-16 with a terminating NUL.
BinaryUTF16NUL.transcribe_value(value: str, encoding='utf-16'):
Transcribe value in UTF-16 with a terminating NUL.
BinaryUTF8NUL.VALUE_TYPE
BinaryUTF8NUL.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> str:
Read a NUL terminated UTF-8 string from bfr, return field.
BinaryUTF8NUL.transcribe_value(s):
Transcribe the value in UTF-8 with a terminating NUL.
-
binclass(*da, **dkw): A decorator fordataclass-like binary classes.Example use:
>>> @binclass ... class SomeStruct: ... """A struct containing a count and some flags.""" ... count : UInt32BE ... flags : UInt8 >>> ss = SomeStruct(count=3, flags=0x04) >>> ss SomeStruct:SomeStruct__dataclass(count=UInt32BE('>L',value=3),flags=UInt8('B',value=4)) >>> print(ss) SomeStruct(count=3,flags=4) >>> bytes(ss) b'\x00\x00\x00\x03\x04' >>> SomeStruct.promote(b'\x00\x00\x00\x03\x04') SomeStruct:SomeStruct__dataclass(count=UInt32BE('>L',value=3),flags=UInt8('B',value=4))Extending an existing
@binclassclass, for example to add the body of a structure to some header part:>>> @binclass ... class HeaderStruct: ... """A header containing a count and some flags.""" ... count : UInt32BE ... flags : UInt8 >>> @binclass ... class Packet(HeaderStruct): ... body_text : BSString ... body_data : BSData ... body_longs : BinaryStruct( ... 'longs', '>LL', 'long1 long2' ... ) >>> packet = Packet( ... count=5, flags=0x03, ... body_text="hello", ... body_data=b'xyzabc', ... body_longs=(10,20), ... ) >>> packet Packet:Packet__dataclass(count=UInt32BE('>L',value=5),flags=UInt8('B',value=3),body_text=BSString('hello'),body_data=BSData(b'xyzabc'),body_longs=longs('>LL',long1=10,long2=20)) >>> print(packet) Packet(count=5,flags=3,body_text=hello,body_data=b'xyzabc',body_longs=longs(long1=10,long2=20)) >>> packet.body_data b'xyzabc' -
Classbs(builtins.bytes): Abytes subclass with a compactrepr().
bs.join(self, chunks):
bytes.join but returning a bs.
bs.promote(obj):
Promote bytes or memoryview to a bs.
ClassBSData(BinarySingleValue): A run length encoded data chunk, with the length encoded as aBSUInt`.
BSData.data:
An alias for the .value attribute.
BSData.data_offset:
The length of the length indicator,
useful for computing the location of the raw data.
BSData.data_offset_for(bs) -> int:
Compute the data_offset which would obtain for the bytes bs.
BSData.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> bytes:
Parse the data from bfr.
BSData.transcribe_value(data):
Transcribe the payload length and then the payload.
BSSFloat.VALUE_TYPE
BSSFloat.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> float:
Parse a BSSFloat from a buffer and return the float.
BSSFloat.transcribe_value(f):
Transcribe a float.
ClassBSString(BinarySingleValue)`: A run length encoded string, with the length encoded as a BSUInt.
BSString.VALUE_TYPE
BSString.parse_value(bfr: cs.buffer.CornuCopyBuffer, encoding='utf-8', errors='strict') -> str:
Parse a run length encoded string from bfr.
BSString.transcribe_value(value: str, encoding='utf-8'):
Transcribe a string.
-
ClassBSUInt(BinarySingleValue): A binary serialised unsignedint`.This uses a big endian byte encoding where continuation octets have their high bit set. The bits contributing to the value are in the low order 7 bits.
BSUInt.VALUE_TYPE
BSUInt.decode_bytes(data, offset=0) -> Tuple[int, int]:
Decode an extensible byte serialised unsigned int from data at offset.
Return value and new offset.
Continuation octets have their high bit set. The octets are big-endian.
If you just have a bytes instance, this is the go. If you're
reading from a stream you're better off with parse or parse_value.
Examples:
>>> BSUInt.decode_bytes(b'\0')
(0, 1)
Note: there is of course the usual AbstractBinary.parse_bytes
but that constructs a buffer to obtain the individual bytes;
this static method will be more performant
if all you are doing is reading this serialisation
and do not already have a buffer.
BSUInt.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse an extensible byte serialised unsigned int from a buffer.
Continuation octets have their high bit set. The value is big-endian.
This is the go for reading from a stream. If you already have
a bare bytes instance then the .decode_bytes static method
is probably most efficient;
there is of course the usual AbstractBinary.parse_bytes
but that constructs a buffer to obtain the individual bytes.
BSUInt.transcribe_value(n):
Encode an unsigned int as an entensible byte serialised octet
sequence for decode. Return the bytes object.
-
flatten(transcription) -> Iterable[bytes]: Flattentranscriptioninto an iterable ofBuffers. None of theBuffers will be empty.This exists to allow subclass methods to easily return transcribable things (having a
.transcribemethod), ASCII strings or bytes or iterables or evenNone, in turn allowing them simply to return their superclass' chunks iterators directly instead of having to unpack them.The supplied
transcriptionmay be any of the following:None: yield nothing- an object with a
.transcribemethod: yield fromflatten(transcription.transcribe()) - a
Buffer: yield theBufferif it is not empty - a
str: yieldtranscription.encode('ascii') - an iterable: yield from
flatten(item)for each item intranscription
An example from the
cs.iso14496.METABoxBodyclass:def transcribe(self): yield super().transcribe() yield self.theHandler yield self.boxesThe binary classes
flattenthe result of the.transcribemethod to obtainbytesinstances for the object's binary transcription. -
ClassFloat64BE(Float64BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>d'` and presents the attributes ['value'].
Float64BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Float64BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> float:
Parse a value from bfr, return the value.
Float64BE.promote(obj):
Promote a single value to an instance of cls.
Float64BE.transcribe(self):
Transcribe via struct.pack.
Float64BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassFloat64LE(Float64LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<d'` and presents the attributes ['value'].
Float64LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Float64LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> float:
Parse a value from bfr, return the value.
Float64LE.promote(obj):
Promote a single value to an instance of cls.
Float64LE.transcribe(self):
Transcribe via struct.pack.
Float64LE.transcribe_value(value):
Transcribe a value back into bytes.
ClassInt16BE(Int16BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>h'` and presents the attributes ['value'].
Int16BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Int16BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
Int16BE.promote(obj):
Promote a single value to an instance of cls.
Int16BE.transcribe(self):
Transcribe via struct.pack.
Int16BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassInt16LE(Int16LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<h'` and presents the attributes ['value'].
Int16LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Int16LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
Int16LE.promote(obj):
Promote a single value to an instance of cls.
Int16LE.transcribe(self):
Transcribe via struct.pack.
Int16LE.transcribe_value(value):
Transcribe a value back into bytes.
ClassInt32BE(Int32BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>l'` and presents the attributes ['value'].
Int32BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Int32BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
Int32BE.promote(obj):
Promote a single value to an instance of cls.
Int32BE.transcribe(self):
Transcribe via struct.pack.
Int32BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassInt32LE(Int32LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<l'` and presents the attributes ['value'].
Int32LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
Int32LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
Int32LE.promote(obj):
Promote a single value to an instance of cls.
Int32LE.transcribe(self):
Transcribe via struct.pack.
Int32LE.transcribe_value(value):
Transcribe a value back into bytes.
-
is_single_value(obj): Test whetherobjis a single value binary object.This currently recognises
BinarySingleValueinstances and tuple basedAbstractBinaryinstances of length 1. -
parse_offsets(*da, **dkw): Decorateparse(usually anAbstractBinaryclass method) to record the buffer starting offset asself.offsetand the buffer post parse offset asself.end_offset. If the decorator parameterreportis true, callbfr.report_offset()with the starting offset at the end of the parse. -
pt_spec(pt, name=None, value_type=None, as_repr=None, as_str=None): Convert a parse/transcribe specificationptinto anAbstractBinarysubclass.This is largely used to provide flexibility in the specifications for the
BinaryMultiValuefactory but can also be used as a factory for other simple classes.If the specification
ptis a subclass ofAbstractBinarythis is returned directly.If
ptis a (str,str) 2-tuple the values are presumed to be a format string forstruct.structand field names separated by spaces; a newBinaryStructclass is created from these and returned.Otherwise two functions
f_parse_value(bfr)andf_transcribe_value(value)are obtained and used to construct a newBinarySingleValueclass as follows:If
pthas.parse_valueand.transcribe_valuecallable attributes, use those forf_parse_valueandf_transcribe_valuerespectively.Otherwise, if
ptis anintdefinef_parse_valueto obtain exactly that many bytes from a buffer andf_transcribe_valueto return those bytes directly.Otherwise presume
ptis a 2-tuple of(f_parse_value,f_transcribe_value). -
ClassSimpleBinary(types.SimpleNamespace, AbstractBinary): Abstract binary class based on aSimpleNamespace, thus providing a nicestrand a keyword basedinit. Implementors must still define.parseand.transcribe`.To constrain the arguments passed to
__init__, define an__init__which accepts specific keyword arguments and pass through tosuper().__init__(). Example:def __init__(self, *, field1=None, field2): """ Accept only `field1` (optional) and `field2` (mandatory). """ super().__init__(field1=field1, field2=field2) -
struct_field_types(struct_format: str, field_names: Union[str, Iterable[str]]) -> Mapping[str, type]: Construct adictmapping field names to struct return types.Example:
>>> struct_field_types('>Hs', 'count text_bs') {'count': <class 'int'>, 'text_bs': <class 'bytes'>} -
ClassUInt16BE(UInt16BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>H'` and presents the attributes ['value'].
UInt16BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt16BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt16BE.promote(obj):
Promote a single value to an instance of cls.
UInt16BE.transcribe(self):
Transcribe via struct.pack.
UInt16BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt16LE(UInt16LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<H'` and presents the attributes ['value'].
UInt16LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt16LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt16LE.promote(obj):
Promote a single value to an instance of cls.
UInt16LE.transcribe(self):
Transcribe via struct.pack.
UInt16LE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt32BE(UInt32BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>L'` and presents the attributes ['value'].
UInt32BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt32BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt32BE.promote(obj):
Promote a single value to an instance of cls.
UInt32BE.transcribe(self):
Transcribe via struct.pack.
UInt32BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt32LE(UInt32LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<L'` and presents the attributes ['value'].
UInt32LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt32LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt32LE.promote(obj):
Promote a single value to an instance of cls.
UInt32LE.transcribe(self):
Transcribe via struct.pack.
UInt32LE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt64BE(UInt64BE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'>Q'` and presents the attributes ['value'].
UInt64BE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt64BE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt64BE.promote(obj):
Promote a single value to an instance of cls.
UInt64BE.transcribe(self):
Transcribe via struct.pack.
UInt64BE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt64LE(UInt64LE, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'<Q'` and presents the attributes ['value'].
UInt64LE.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt64LE.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt64LE.promote(obj):
Promote a single value to an instance of cls.
UInt64LE.transcribe(self):
Transcribe via struct.pack.
UInt64LE.transcribe_value(value):
Transcribe a value back into bytes.
ClassUInt8(UInt8, AbstractBinary): AnAbstractBinarynamedtuplewhich parses and transcribes the struct format'B'` and presents the attributes ['value'].
UInt8.parse(bfr: cs.buffer.CornuCopyBuffer):
Parse from bfr via struct.unpack.
UInt8.parse_value(bfr: cs.buffer.CornuCopyBuffer) -> int:
Parse a value from bfr, return the value.
UInt8.promote(obj):
Promote a single value to an instance of cls.
UInt8.transcribe(self):
Transcribe via struct.pack.
UInt8.transcribe_value(value):
Transcribe a value back into bytes.
Release Log
Release 20250501:
- @binclass: a dataclass-like way to specify binary structures.
- Rename BinaryByteses to BinaryBytes.
- Rename BinaryMultiStruct and BinarySingleStruct to BinaryStruct.
- New bs(bytes) subclass with a compact repr().
- BinarySingleValue classes now expect a type specification for the value.
- BinarySingleValue now subclasses cs.deco.Promotable.
- New struct_field_types(struct_format,field_names) to return a mapping of field names to struct.unpack-returned types.
- New is_single_value(obj) to test for single value binary objects.
- New ListOfBinary, a class holding a list of instances of some binary class.
- Many internal updates and improvements.
Release 20240630:
- flatten: do not yield empty str-as-ascii-bytes - we want to ensure that flatten never yields an empty bytes instance.
- New AbstractBinary.write(f) method to write the binary form of this object to a file.
- New BinarySingleValue.value_from_bytes(bytes) class method to return the value from a bytes instance.
- Drop BinaryMixin, now folded directly into AbstractBinary.
- AbstractBinary.scan: pass extra keyword arguments to AbstractBinary.parse, supporting plumbing eg a logging parameter through.
Release 20240422: New _BinaryMultiValue_Base.for_json() method returning a dict containing the fields.
Release 20240316: Fixed release upload artifacts.
Release 20240201: BREAKING CHANGE: drop the long deprecated PacketField related classes.
Release 20231129: BinaryMultiStruct.parse: promote the buffer arguments to a CornuCopyBuffer.
Release 20230401:
- BinaryMixin.scan:
bfrparameter may be any object acceptable to CornuCopyBuffer.promote. - BinaryMixin.scan: accept new optional with_offsets parameter; deprecate scan_with_offsets and scan_fspathi in favour of scan.
Release 20230212:
- BinaryMixin: new load(file) and save(file) methods.
- BinaryMixin.scan: promote the bfr argument.
Release 20221206: Documentation fix.
Release 20220605: BinaryMixin: replace scan_file with scan_fspath, as the former left uncertainty about the amount of the file consumed.
Release 20210316:
- BSUInt: rename parse_bytes to decode_bytes, the former name conflicted with BinaryMixin.parse_bytes and broken the semantics.
- Minor refactors.
Release 20210306: MAJOR RELEASE: The PacketField classes and friends were hard to use; this release supplied a suite of easier to use and more consistent Binary* classes, and ports most of those things based on the old scheme to the new scheme.
Release 20200229:
- ListField: replace transcribe method with transcribe_value method, aids external use.
- Add
.lengthattribute to struct based packet classes providing the data length of the structure (struct.Struct.size). - Packet: new
add_deferred_fieldmethod to consume the raw data for a field for parsing later (done automatically if the attribute is accessed). - New
@deferred_fielddecorator for the parser for that stashed data.
Release 20191230.3: Docstring tweak.
Release 20191230.2: Documentation updates.
Release 20191230.1: Docstring updates. Semantic changes were in the previous release.
Release 20191230:
- ListField: new iter method.
- Packet: str: accept optional
skip_fieldsparameter to omit some field names. - Packet: new .add_from_value method to add a named field with a presupplied value.
- Packet: new remove_field(field_name) and pop_field() methods to remove fields.
- BytesesField: iter yields the bytes values, transcribe=iter.
- PacketField: propagate keyword arguments through various methods, required for parameterised PacketFields.
- New UTF16NULField, a NUL terminated UTF16 string.
- PacketField: provide a default
.transcribe_valuemethod which makes a new instance and calls its.transcribemethod. - Documentation update and several minor changes.
Release 20190220:
- Packet.self_check: fields without a sanity check cause a warning, not a ValueError.
- New Float64BE, Float64LE and BSSFloat classes for IEEE floats and floats-as-strings.
- Additional module docstringage on subclassing Packet and PacketField.
- BSString: drop redundant from_buffer class method.
- PacketField.init: default to value=None if omitted.
Release 20181231: flatten: do not yield zero length bytelike objects, can be misread as EOF on some streams.
Release 20181108:
- New PacketField.transcribe_value_flat convenience method to return a flat iterable of bytes-like objects.
- New PacketField.parse_buffer generator method to parse instances of the PacketField from a buffer until end of input.
- New PacketField.parse_buffer_values generator method to parse instances of the PacketField from a buffer and yield the
.valueattribute until end of input.
Release 20180823:
- Some bugfixes.
- Define PacketField.eq.
- BSUInt, BSData and BSString classes implementing the serialisations from cs.serialise.
- New PacketField.value_from_bytes class method.
- New PacketField.value_from_buffer method.
Release 20180810.2: Documentation improvements.
Release 20180810.1: Improve module description.
Release 20180810: BytesesField.from_buffer: make use of the buffer's skipto method if discard_data is true.
Release 20180805:
- Packet: now an abstract class, new self_check method initially checking the
- PACKET_FIELDS class attribute against the instance, new methods get_field
- and set_field to fetch or replace existing fields, allow keyword arguments
- to initialise the Packet fields and document the dependency on keyword
- argument ordering.
- PacketField: len computed directory from a transcribe, drop other len
- methods.
- EmptyField singleton to use as a placeholder for missing optional fields.
- BytesField: implement value_s and from_buffer.
- multi_struct_field: implement len for generated class.
- flatten: treat memoryviews like bytes.
- Assorted docstrings and fixes.
Release 20180801: Initial PyPI release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cs_binary-20250501.tar.gz.
File metadata
- Download URL: cs_binary-20250501.tar.gz
- Upload date:
- Size: 49.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04d20bd1303309fcfcab68d2a966db09cd15f3483935f85c3f0ba0fe2ec270a3
|
|
| MD5 |
636c61fd9c0932f6a02956538bb585e7
|
|
| BLAKE2b-256 |
6b35e999b3e4280127992c2b5055d36cc7aeb21d7db105efd2f69d7035a6697d
|
File details
Details for the file cs_binary-20250501-py3-none-any.whl.
File metadata
- Download URL: cs_binary-20250501-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0539e69e005c8fca6630aac27d713ea0b2cbcdce187b1a22be16c7067c447643
|
|
| MD5 |
421b422ab42e659055a225754c62de05
|
|
| BLAKE2b-256 |
50cac14e33da02b928319ff1ce37a2cab91df3873a947fb62e5972faede9a1f7
|