Python BinField implementation for binary data manipulation
Project description
binfield
Python binfield implementation for binary data manipulation.
Why? Python supports binary data manipulation via binary operations out of the box and it’s fast, but it’s hard to read and painful during prototyping, especially for complex (nested) structures.
This library is desined to fix this issue: it allows to operate with binary data like dict with constant indexes: you just need to define structure class and create an instance with start data. Now you can use indexes for reading and writing data
Pros:
Free software: Apache license
Open Source: https://github.com/penguinolog/binfield
Self-documented code: docstrings with types in comments
Tested: see bages on top
Support multiple Python versions:
Python 2.7 Python 3.4 Python 3.5 Python 3.6 PyPy PyPy3 Jyton 2.7
Usage
Not mapped objects could be created simply from BinField class:
bf = BinField(42)
Data with fixed size should be created as new class (type): Example on real data (ZigBee frame control field):
# Describe
class ZBFrameControl(binfield.BinField):
_size_ = 16 # Optional, used as source for mask, if mask is not defined
_mask_ = 0xFF7F # Optional, used as source for size, if size is not defined
FrameType = [0, 3] # Enum
Security = 3
FramePending = 4
AckRequest = 5
PAN_ID_Compression = 6
SequrityNumberSuppress = 8
InformationPresent = 9
DstAddrMode = [10, 12]
FrameVersion = [12, 14]
SrcAddrMode = [14, 16]
# Construct from frame
# (limitation: endianless convertation is not supported, make it by another tools)
frame = frame = ZBFrameControl(0x0803) # Beacon request
>>> print(frame)
<2051 == 0x0803 == (0b0000100000000011 & 0b1111111111111111)
FrameType = <3 == 0x03 == (0b011 & 0b111)>
Security = <0 == 0x00 == (0b0 & 0b1)>
FramePending = <0 == 0x00 == (0b0 & 0b1)>
AckRequest = <0 == 0x00 == (0b0 & 0b1)>
PAN_ID_Compression = <0 == 0x00 == (0b0 & 0b1)>
SequrityNumberSuppress = <0 == 0x00 == (0b0 & 0b1)>
InformationPresent = <0 == 0x00 == (0b0 & 0b1)>
DstAddrMode = <2 == 0x02 == (0b10 & 0b11)>
FrameVersion = <0 == 0x00 == (0b00 & 0b11)>
SrcAddrMode = <0 == 0x00 == (0b00 & 0b11)>
>>> repr(frame)
'ZBFrameControl(x=0x0803, base=16)'
>>> print(frame.FrameType)
<3 == 0x03 == (0b011 & 0b111)> # Get nested structure: current is flat, so we have single value
# We can use slice to get bits from value: result type is always subclass of BinField
>>> repr(frame.FrameType[: 2])
'<FrameType_slice_0_2(x=0x03, base=16) at 0x7FD0ACA57408>'
>>> frame.FrameType == 3 # Transparent comparsion with integers
True
>>> int(frame.FrameType) # Painless conversion to int
3
>>> bool(frame.AckRequest) # And bool
False
>>> print(frame[1: 5]) # Ignore indexes and just get few bits using slice
<1 == 0x01 == (0b0001 & 0b1111)>
>>> print(ZBFrameControl.AckRequest) # Request indexes from created data type
5
>>> print(ZBFrameControl.DstAddrMode) # Multiple bits too
slice(10, 12, None)
# Modification of nested data (if no type conversion was used) changes original object:
>>> frame.AckRequest = 1
>>> print(frame)
<2083 == 0x0823 == (0b0000100000100011 & 0b1111111101111111)
FrameType = <3 == 0x03 == (0b011 & 0b111)>
Security = <0 == 0x00 == (0b0 & 0b1)>
FramePending = <0 == 0x00 == (0b0 & 0b1)>
AckRequest = <1 == 0x01 == (0b1 & 0b1)>
PAN_ID_Compression = <0 == 0x00 == (0b0 & 0b1)>
SequrityNumberSuppress = <0 == 0x00 == (0b0 & 0b1)>
InformationPresent = <0 == 0x00 == (0b0 & 0b1)>
DstAddrMode = <2 == 0x02 == (0b10 & 0b11)>
FrameVersion = <0 == 0x00 == (0b00 & 0b11)>
SrcAddrMode = <0 == 0x00 == (0b00 & 0b11)>
>
# But remember, that nested blocks has it's own classes
>>> repr(frame.DstAddrMode)
'<DstAddrMode(x=0x02, base=16) at 0x7FD0AD139548>'
>>> fr2 = ZBFrameControl(0xFFFF)
>>> repr(fr2)
'ZBFrameControl(x=0xFF7F, base=16)' # Mask if applied, if defined
# Fields could be set only from integers
>>> frame.SrcAddrMode = fr2.SrcAddrMode
Traceback (most recent call last):
...
TypeError: BinField value could be set only as int
>>> repr(frame['FramePending']) # __getitem__ and __setitem__ is supported
'<FramePending(x=0x00, base=16) at 0x7FD0ACAD3188>'
Nested structures is supported, if required. Definition example (not aligned with any real data):
class NestedMappedBinField(BinField):
test_index = 0
nested_block = {
'_index_': (1, 6),
'single_bit': 0,
'multiple': (1, 3)
}
Note: negative indexes is not supported by design!
Testing
The main test mechanism for the package binfield is using tox. Test environments available:
pep8 py27 py34 py35 py36 pypy pypy3 jyton pylint
CI systems
For code checking several CI systems is used in parallel:
Travis CI: is used for checking: PEP8, pylint, bandit, installation possibility and unit tests. Also it’s publishes coverage on coveralls.
coveralls: is used for coverage display.
CD system
Travis CI: is used for package delivery on PyPI.
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
File details
Details for the file BinField-0.7.1.tar.gz
.
File metadata
- Download URL: BinField-0.7.1.tar.gz
- Upload date:
- Size: 21.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8d0cd566668e208e0e723d076c838ceb4d7fb851e634ba182e6c7206a1436f84 |
|
MD5 | c4466f06933e731b2cdae31274755929 |
|
BLAKE2b-256 | 0dc855d2f458b650a6fdd21745344be54576f23112f89588ecb7ee840b070784 |
Provenance
File details
Details for the file BinField-0.7.1-py2.py3-none-any.whl
.
File metadata
- Download URL: BinField-0.7.1-py2.py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9879780bee787b4bf9ddc2439c74bc098692e585569f128eeece280c255fe39f |
|
MD5 | 9ad022a6f55c499bf2b89ca149a31706 |
|
BLAKE2b-256 | 484e06068d4559cf8eb5d91680040bb6875c861307eab1fbb5cf9cf36c4a9aac |