{ "info": { "author": "Gehn", "author_email": "use-github-issues@example.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Code Generators", "Topic :: Software Development :: Compilers", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "bisturi\n=======\n\nBisturi is a library to parse binary data in the less painful way: no\nneed to write 'for' loops neither nested 'if' conditionals. It's a kind\nof 'what you see see is what you mean' parser which will allow you to\npack and unpack bytes in a declarative way.\n\nLet's see bisturi by examples.\n\nThis is the classical Type-Length-Value packet and how we can describe\nit in bisturi.\n\n.. code:: python\n\n >>> from bisturi.packet import Packet\n >>> from bisturi.field import Int, Data\n\n >>> class TypeLengthValue(Packet):\n ... type = Int(1)\n ... length = Int(2)\n ... value = Data(length)\n\n>From the source it's easy to see that the type is an integer of 1 byte\nmeanwhile the length is an integer of size 2. The value is a data of\nvariable size of length bytes.\n\nThat's all what you need. The principal objective of bisturi is to allow\nyou to write simple classes easy to read and understand hidding almost\neverything parsing details behind the scene.\n\nAfter the packet definition you can parse any byte string in one call:\n\n.. code:: python\n\n >>> raw = b'\\t\\x00\\x04ABCD'\n >>> tlv = TypeLengthValue.unpack(raw)\n\n >>> tlv.type\n 9\n >>> tlv.length\n 4\n >>> tlv.value\n 'ABCD'\n\nAs well you can parse (unpack) a byte string you can do the reverse,\npack a packet into a byte string:\n\n.. code:: python\n\n >>> tlv.pack()\n '\\t\\x00\\x04ABCD'\n\nInt and Data are not the only fields available. Here is an example of\nhow to describe a bit mask\n\n.. code:: python\n\n >>> from bisturi.field import Bits\n\n >>> class FrameControl(Packet):\n ... length = Bits(6)\n ... more_fragments = Bits(1)\n ... fragment_offset = Bits(9)\n ... data = Data(length)\n\n >>> raw = b'\\x0c\\x05abc'\n >>> fc = FrameControl.unpack(raw)\n\n >>> fc.length\n 3\n >>> fc.more_fragments\n 0\n >>> fc.fragment_offset\n 5\n >>> fc.data\n 'abc'\n\nAnd here is how to describe a sequence of values (aka list) and an\noptional field:\n\n.. code:: python\n\n >>> class Image1D(Packet):\n ... has_name = Bits(1)\n ... count_numbers = Bits(7)\n ...\n ... numbers = Int(1).repeated(count_numbers)\n ... optional_name = Data(until_marker=b'\\x00').when(has_name)\n\n >>> raw_without_name = b'\\x03ABC'\n >>> image1d = Image1D.unpack(raw_without_name)\n\n >>> image1d.has_name\n 0\n >>> image1d.count_numbers\n 3\n >>> image1d.numbers\n [65, 66, 67]\n >>> image1d.optional_name is None\n True\n\n >>> raw_with_name = b'\\x83ABCsome null terminated name\\x00garbage-garbage'\n >>> image1d = Image1D.unpack(raw_with_name)\n\n >>> image1d.has_name\n 1\n >>> image1d.numbers\n [65, 66, 67]\n >>> image1d.optional_name\n 'some null terminated name'\n\nNot only you can use the single value of a field to define the size or\nthe count of other field but you can describe arbitrary expressions or\neven use a callable for the more complex one that require statements\n(which in Python they aren't expressions; think in 'if' statements).\n\nHere is what I mean:\n\n.. code:: python\n\n >>> class Matrix(Packet):\n ... rows = Int(1)\n ... columns = Int(1)\n ...\n ... values = Int(1).repeated(rows * columns) # arithmetic operations\n\n >>> class Address(Packet):\n ... ip_address = Int(1).repeated(4)\n ... domain_name = Data(until_marker=b'\\x00').when((ip_address[:3] == [0, 0, 0]) &\n ... (ip_address[3] != 0)) # subscript and comparisions\n\n >>> class Token(Packet):\n ... size = Int(1)\n ... data = Data(byte_count = lambda pkt, raw, offset, **k: pkt.size if pkt.size < 8 else 8)\n ... # ^-- an arbitrary callable is allowed too\n\n\n >>> raw_matrix = b'\\x02\\x03ABCDEF'\n >>> matrix_2x3 = Matrix.unpack(raw_matrix)\n\n >>> cols = matrix_2x3.columns\n >>> matrix_2x3.values[0 : cols] # first row\n [65, 66, 67]\n >>> matrix_2x3.values[cols : cols*2] # second row\n [68, 69, 70]\n\n >>> raw_resolved_address = b'\\xc0\\xa8\\x00\\x01'\n >>> resolved_address = Address.unpack(raw_resolved_address)\n\n >>> resolved_address.ip_address\n [192, 168, 0, 1]\n >>> resolved_address.domain_name is None\n True\n\n >>> raw_unresolved_address = b'\\x00\\x00\\x00\\x01example.com\\x00'\n >>> unresolved_address = Address.unpack(raw_unresolved_address)\n\n >>> unresolved_address.ip_address\n [0, 0, 0, 1]\n >>> unresolved_address.domain_name\n 'example.com'\n\n >>> raw_small_token = b'\\x01A'\n >>> small_token = Token.unpack(raw_small_token)\n\n >>> small_token.data\n 'A'\n\n >>> raw_too_long_token = b'\\xffABCD1234EFGH5678'\n >>> truncated_token = Token.unpack(raw_too_long_token)\n\n >>> truncated_token.data\n 'ABCD1234'\n\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/gehnch/bisturi", "keywords": "parse parsing binary network file compiler code generator", "license": "GNU LGPLv3", "maintainer": "", "maintainer_email": "", "name": "bisturi", "package_url": "https://pypi.org/project/bisturi/", "platform": "", "project_url": "https://pypi.org/project/bisturi/", "project_urls": { "Homepage": "https://github.com/gehnch/bisturi" }, "release_url": "https://pypi.org/project/bisturi/0.5.0/", "requires_dist": null, "requires_python": ">=2.6", "summary": "Parse binary data painless describing the packets' structures in python classes: no need to write 'for' loops or nested 'if' conditionals.", "version": "0.5.0" }, "last_serial": 3602097, "releases": { "0.5.0": [ { "comment_text": "", "digests": { "md5": "480df15fe795a34e8149f10b8269a77b", "sha256": "e726779db4fa78e00e3d52eb23e4031398c3e67afd5e048ce5dff928db40d346" }, "downloads": -1, "filename": "bisturi-0.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "480df15fe795a34e8149f10b8269a77b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.6", "size": 33913, "upload_time": "2018-02-21T13:17:40", "url": "https://files.pythonhosted.org/packages/25/ba/2867c9e43a8bcb583042083a0789b75f61c88a56f16f2c298806de2dff37/bisturi-0.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b3f890f5c3d538e0b1353c0a3672a4fe", "sha256": "056f0c6676b4b567acc41fe32dfc4d9a71d09c25e035434340ed939003690051" }, "downloads": -1, "filename": "bisturi-0.5.0.tar.gz", "has_sig": false, "md5_digest": "b3f890f5c3d538e0b1353c0a3672a4fe", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.6", "size": 29127, "upload_time": "2018-02-21T13:17:42", "url": "https://files.pythonhosted.org/packages/47/d7/cc3c7d16a93e150e89da2952077c66733d6a6aac62bd0e522ea8e7e0f33d/bisturi-0.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "480df15fe795a34e8149f10b8269a77b", "sha256": "e726779db4fa78e00e3d52eb23e4031398c3e67afd5e048ce5dff928db40d346" }, "downloads": -1, "filename": "bisturi-0.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "480df15fe795a34e8149f10b8269a77b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.6", "size": 33913, "upload_time": "2018-02-21T13:17:40", "url": "https://files.pythonhosted.org/packages/25/ba/2867c9e43a8bcb583042083a0789b75f61c88a56f16f2c298806de2dff37/bisturi-0.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b3f890f5c3d538e0b1353c0a3672a4fe", "sha256": "056f0c6676b4b567acc41fe32dfc4d9a71d09c25e035434340ed939003690051" }, "downloads": -1, "filename": "bisturi-0.5.0.tar.gz", "has_sig": false, "md5_digest": "b3f890f5c3d538e0b1353c0a3672a4fe", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.6", "size": 29127, "upload_time": "2018-02-21T13:17:42", "url": "https://files.pythonhosted.org/packages/47/d7/cc3c7d16a93e150e89da2952077c66733d6a6aac62bd0e522ea8e7e0f33d/bisturi-0.5.0.tar.gz" } ] }