{"id":16759687,"url":"https://github.com/penguinolog/binfield","last_synced_at":"2025-06-13T18:38:04.649Z","repository":{"id":57415108,"uuid":"75631824","full_name":"penguinolog/binfield","owner":"penguinolog","description":"Python BinField implementation","archived":false,"fork":false,"pushed_at":"2020-11-18T16:10:52.000Z","size":194,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-28T14:54:11.300Z","etag":null,"topics":["binary-data","data-type","py3","python","python-3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/penguinolog.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-05T14:21:27.000Z","updated_at":"2020-11-18T16:10:55.000Z","dependencies_parsed_at":"2022-09-01T16:41:40.214Z","dependency_job_id":null,"html_url":"https://github.com/penguinolog/binfield","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/penguinolog/binfield","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penguinolog%2Fbinfield","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penguinolog%2Fbinfield/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penguinolog%2Fbinfield/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penguinolog%2Fbinfield/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/penguinolog","download_url":"https://codeload.github.com/penguinolog/binfield/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penguinolog%2Fbinfield/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259699938,"owners_count":22898358,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary-data","data-type","py3","python","python-3"],"created_at":"2024-10-13T04:08:48.765Z","updated_at":"2025-06-13T18:38:04.621Z","avatar_url":"https://github.com/penguinolog.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"binfield\n========\n\n.. image:: https://travis-ci.org/penguinolog/binfield.svg?branch=master\n    :target: https://travis-ci.org/penguinolog/binfield\n.. image:: https://coveralls.io/repos/github/penguinolog/binfield/badge.svg?branch=master\n    :target: https://coveralls.io/github/penguinolog/binfield?branch=master\n.. image:: https://readthedocs.org/projects/binfield/badge/?version=latest\n    :target: https://binfield.readthedocs.io\n    :alt: Documentation Status\n.. image:: https://img.shields.io/pypi/v/binfield.svg\n    :target: https://pypi.python.org/pypi/binfield\n.. image:: https://img.shields.io/pypi/pyversions/binfield.svg\n    :target: https://pypi.python.org/pypi/binfield\n.. image:: https://img.shields.io/pypi/status/binfield.svg\n    :target: https://pypi.python.org/pypi/binfield\n.. image:: https://img.shields.io/github/license/penguinolog/binfield.svg\n    :target: https://raw.githubusercontent.com/penguinolog/binfield/master/LICENSE\n\nPython binfield implementation for binary data manipulation.\n\n    Why? Python supports binary data manipulation via binary operations out of the box and it's fast,\n    but it's hard to read and painful during prototyping, especially for complex (nested) structures.\n\n    This library is designed to fix this issue: it allows to operate with binary data like dict with constant indexes:\n    you just need to define structure class and create an instance with start data.\n    Now you can use indexes for reading and writing data\n\n**Pros**:\n\n* Free software: Apache license\n* Open Source: https://github.com/penguinolog/binfield\n* Self-documented code: docstrings with types in comments\n* Tested: see badges on top\n* Support multiple Python versions:\n\n::\n\n    Python 3.6\n    Python 3.7\n    PyPy3\n\nUsage\n=====\n\nNot mapped objects can be created simply from BinField class:\n\n.. code-block:: python\n\n    bf = BinField(42)\n\nData with fixed size should be created as a new class (type):\nExample on real data (ZigBee frame control field):\n\n.. code-block:: python\n\n    # Describe\n    class ZBFrameControl(binfield.BinField):\n        _size_ = 16  # Optional, used as source for mask, if mask is not defined\n        _mask_ = 0xFF7F  # Optional, used as source for size, if size is not defined\n        FrameType = [0, 3]  # Enum\n        Security = 3\n        FramePending = 4\n        AckRequest = 5\n        PAN_ID_Compression = 6\n        SecurityNumberSuppress = 8\n        InformationPresent = 9\n        DstAddrMode = [10, 12]\n        FrameVersion =  [12, 14]\n        SrcAddrMode = [14, 16]\n\n    # Construct from frame\n    # (limitation: endian conversion is not supported, make it using another tools)\n    frame = frame = ZBFrameControl(0x0803)  # Beacon request\n\n    \u003e\u003e\u003e print(frame)\n    \u003c2051 == 0x0803 == (0b0000100000000011 \u0026 0b1111111111111111)\n      FrameType             = \u003c3 == 0x03 == (0b011 \u0026 0b111)\u003e\n      Security               = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      FramePending           = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      AckRequest             = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      PAN_ID_Compression     = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      SecurityNumberSuppress = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      InformationPresent     = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      DstAddrMode            = \u003c2 == 0x02 == (0b10 \u0026 0b11)\u003e\n      FrameVersion           = \u003c0 == 0x00 == (0b00 \u0026 0b11)\u003e\n      SrcAddrMode            = \u003c0 == 0x00 == (0b00 \u0026 0b11)\u003e\n\n    \u003e\u003e\u003e repr(frame)\n    'ZBFrameControl(x=0x0803, base=16)'\n\n    \u003e\u003e\u003e print(frame.FrameType)\n    \u003c3 == 0x03 == (0b011 \u0026 0b111)\u003e  # Get nested structure: current is flat, so we have single value\n\n    # We can use slice to get bits from value: result type is always subclass of BinField\n    \u003e\u003e\u003e repr(frame.FrameType[: 2])\n    '\u003cFrameType_slice_0_2(x=0x03, base=16) at 0x7FD0ACA57408\u003e'\n\n    \u003e\u003e\u003e frame.FrameType == 3  # Transparent comparision with integers\n    True\n\n    \u003e\u003e\u003e int(frame.FrameType)  # Painless conversion to int\n    3\n\n    \u003e\u003e\u003e bool(frame.AckRequest)  # And bool\n    False\n\n    \u003e\u003e\u003e print(frame[1: 5])  # Ignore indexes and just get few bits using slice\n    \u003c1 == 0x01 == (0b0001 \u0026 0b1111)\u003e\n\n    \u003e\u003e\u003e print(ZBFrameControl.AckRequest)  # Request indexes from created data type\n    5\n\n    \u003e\u003e\u003e print(ZBFrameControl.DstAddrMode)  # Multiple bits too\n    slice(10, 12, None)\n\n    # Modification of nested data (if no type conversion was used) changes original object:\n    \u003e\u003e\u003e frame.AckRequest = 1\n    \u003e\u003e\u003e print(frame)\n    \u003c2083 == 0x0823 == (0b0000100000100011 \u0026 0b1111111101111111)\n      FrameType              = \u003c3 == 0x03 == (0b011 \u0026 0b111)\u003e\n      Security               = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      FramePending           = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      AckRequest             = \u003c1 == 0x01 == (0b1 \u0026 0b1)\u003e\n      PAN_ID_Compression     = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      SecurityNumberSuppress = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      InformationPresent     = \u003c0 == 0x00 == (0b0 \u0026 0b1)\u003e\n      DstAddrMode            = \u003c2 == 0x02 == (0b10 \u0026 0b11)\u003e\n      FrameVersion           = \u003c0 == 0x00 == (0b00 \u0026 0b11)\u003e\n      SrcAddrMode            = \u003c0 == 0x00 == (0b00 \u0026 0b11)\u003e\n    \u003e\n\n    # But remember, that nested blocks has it's own classes\n    \u003e\u003e\u003e repr(frame.DstAddrMode)\n    '\u003cDstAddrMode(x=0x02, base=16) at 0x7FD0AD139548\u003e'\n\n    \u003e\u003e\u003e fr2 = ZBFrameControl(0xFFFF)\n    \u003e\u003e\u003e repr(fr2)\n    'ZBFrameControl(x=0xFF7F, base=16)'  # Mask if applied, if defined\n\n    # Fields can be set only from integers\n    \u003e\u003e\u003e frame.SrcAddrMode = fr2.SrcAddrMode\n    Traceback (most recent call last):\n    ...\n    TypeError: BinField value could be set only as int\n\n    \u003e\u003e\u003e repr(frame['FramePending'])  # __getitem__ and __setitem__ is supported\n    '\u003cFramePending(x=0x00, base=16) at 0x7FD0ACAD3188\u003e'\n\n\nNested structures are supported, if required. Definition example (not aligned with any real data):\n\n.. code-block:: python\n\n    class NestedMappedBinField(BinField):\n        test_index = 0\n        nested_block = {\n            '_index_': (1, 6),\n            'single_bit': 0,\n            'multiple': (1, 3)\n        }\n\n    \u003e\u003e\u003e bf = NestedMappedBinField(0xFF)\n    # No _size_ and no _mask_ -\u003e size is not limited,\n    # but indexes can not be changed after class creation\n    \u003e\u003e\u003e print(bf)\n    \u003c255 == 0xFF == (0b11111111)\n      test_index   = \u003c1 == 0x01 == (0b1 \u0026 0b1)\u003e\n      nested_block =\n        \u003c31 == 0x1F == (0b11111 \u0026 0b11111)\n          single_bit = \u003c1 == 0x01 == (0b1 \u0026 0b1)\u003e\n          multiple   = \u003c3 == 0x03 == (0b11 \u0026 0b11)\u003e\n        \u003e\n    \u003e\n\n    # Get nested block: nested block is structured.\n    \u003e\u003e\u003e print(bf.nested_block)\n    \u003c31 == 0x1F == (0b11111 \u0026 0b11111)\n      single_bit = \u003c1 == 0x01 == (0b1 \u0026 0b1)\u003e\n      multiple   = \u003c3 == 0x03 == (0b11 \u0026 0b11)\u003e\n    \u003e\n\n\nNote: *negative indexes are not supported by design!*\n\nTesting\n=======\nMain test mechanism for the package `binfield` uses `tox`.\nTest environments available:\n\n::\n\n    pep8\n    py36\n    pypy3\n    pylint\n    docs\n\nCI systems\n==========\nFor code checking several CI systems are used in parallel:\n\n1. `Travis CI: \u003chttps://travis-ci.org/penguinolog/binfield\u003e`_ is used for checking: PEP8, pylint, bandit, installation possibility and unit tests. Also it publishes coverage on coveralls.\n\n2. `coveralls: \u003chttps://coveralls.io/github/penguinolog/binfield\u003e`_ is used for coverage display.\n\nCD system\n=========\n`Travis CI: \u003chttps://travis-ci.org/penguinolog/binfield\u003e`_ is used for package delivery on PyPI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpenguinolog%2Fbinfield","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpenguinolog%2Fbinfield","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpenguinolog%2Fbinfield/lists"}