Skip to main content

Python BinField implementation for binary data manipulation

Project description

binfield

https://travis-ci.org/penguinolog/binfield.svg?branch=master https://coveralls.io/repos/github/penguinolog/binfield/badge.svg?branch=master Documentation Status https://img.shields.io/pypi/v/binfield.svg https://img.shields.io/pypi/pyversions/binfield.svg https://img.shields.io/pypi/status/binfield.svg https://img.shields.io/github/license/penguinolog/binfield.svg

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:

  1. Travis CI: is used for checking: PEP8, pylint, bandit, installation possibility and unit tests. Also it’s publishes coverage on coveralls.

  2. coveralls: is used for coverage display.

CD system

Travis CI: is used for package delivery on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

BinField-0.7.1.tar.gz (21.4 kB view details)

Uploaded Source

Built Distribution

BinField-0.7.1-py2.py3-none-any.whl (15.3 kB view details)

Uploaded Python 2 Python 3

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

Hashes for BinField-0.7.1.tar.gz
Algorithm Hash digest
SHA256 8d0cd566668e208e0e723d076c838ceb4d7fb851e634ba182e6c7206a1436f84
MD5 c4466f06933e731b2cdae31274755929
BLAKE2b-256 0dc855d2f458b650a6fdd21745344be54576f23112f89588ecb7ee840b070784

See more details on using hashes here.

Provenance

File details

Details for the file BinField-0.7.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for BinField-0.7.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 9879780bee787b4bf9ddc2439c74bc098692e585569f128eeece280c255fe39f
MD5 9ad022a6f55c499bf2b89ca149a31706
BLAKE2b-256 484e06068d4559cf8eb5d91680040bb6875c861307eab1fbb5cf9cf36c4a9aac

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page