{ "info": { "author": "lungdart", "author_email": "dev@lungdart.net", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Topic :: System :: Networking" ], "description": "\n# Packeteer: The packet serializer\n![Travis (.com)](https://img.shields.io/travis/com/lungdart/packeteer.svg)\n![Coveralls github](https://img.shields.io/coveralls/github/lungdart/packeteer.svg)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/packeteer.svg)\n![GitHub](https://img.shields.io/github/license/lungdart/packeteer.svg)\n\n**Packeteer** is a light-weight packet serializer capable of translating between raw bytes and custom packet objects; Objects which are easier to understand, display, and work with\n\n```python\nimport socket\nfrom packeteer import packets, fields\n\nHOST = '127.0.0.1'\nPORT = '1234'\n\nclass Request(packets.BigEndian):\n \"\"\" Request packet \"\"\"\n fields = [\n fields.UInt8('type'),\n fields.UInt8('size'),\n fields.Raw('data', size='size')\n ]\n\nclass Response(packets.BigEndian):\n \"\"\" Response packet \"\"\"\n fields = [\n fields.Bool('success'),\n fields.Uint32('transfered'),\n ]\n\nif __name__ == '__main__':\n data = b'Hello World'\n request = RequestPacket(type=0, data=data)\n response = ResponsePacket()\n\n with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n s.connect()\n s.sendall(request)\n raw = s.recv(response.size())\n response.unpack(raw)\n\n print(repr(response))\n\n# \n# success: True\n# transfered: 11\n```\n\n\n## Installation\n**Packeteer** is available on PyPi, and can be installed with pip directly\n```sh\n$ pip install packeteer\n```\n\n## Requirements\n### Operating systems\n**Packeteer** has no OS dependencies, and should be compatible wherever python can run; However, it is only verified for Ubuntu 18.04. If you discover any issues in other environments, please open a new issue or submit a pull request.\n\n### Python\n**Packeteer** was developed and tested against python 2.7, 3.5, 3.6, and 3.7.\n\n### Dependencies\n**Packeteer** depends on the following packages:\n* future\n* six\n\nFor development and testing, these optional dependencies are also required:\n* pytest\n* pytest-cov\n* tox\n\n## Documentation\n### Defining packets\nDefining packets is as simple as deriving a new class from either *packets.BigEndian* or *packets.LittleEndian* (Depending on the byte ordering of your packet structure)\n\n```python\nimport copy\nfrom packeteer import packets, fields\n\nclass MyPacketBE(packets.BigEndian):\n name = 'Custom (Big Endian)'\n fields = [\n fields.Bool('OK'),\n fields.Int32('value', default=42)\n ]\n\nclass MyPacketLE(packets.LittleEndian):\n \"\"\" Custom (Little Endian) \"\"\"\n fields = copy.deepcopy(MyPacketBE.fields)\n```\n\nTake notice that the packet definition is built using the *fields* variable, and the built-in field types; Field types and there options are explained in the fields section of the documentation.\n\nThe packet name is an optional value that can be set directly, otherwise it will be coppied from the classes doc-string. If no name is found, the name will be given a default value. The name is only used for human readibility when using repr()\n\n### Working with packets\n#### Creating new instances\nWhen packet objects are constructed without any parameters, their default values are stored in each field\n```python\nfrom packeteer import packets, fields\n\nclass MyPacket(packets.BigEndian):\n \"\"\" Custom (Big Endian) \"\"\"\n fields = [\n fields.Bool('OK'),\n fields.Int32('value', default=42)\n ]\n\npacket = MyPacket()\nprint(repr(packet))\n# \n# OK: False\n# value: 42\n```\n\nPackets can also be constructed with non-default values by using the field names to set values\n```python\npacket = MyPacket(OK=True)\nprint(repr(packet))\n# \n# OK: True\n# value: 42\n\npacket2 = MyPacket(value=100)\nprint(repr(packet2))\n# \n# OK: False\n# value: 100\n```\n\n#### Working with packet values\nField values can be accessed like a list (By index) or like a dictionary (By key)\n```python\npacket = MyPacket()\nprint(packet[0], packet[1])\n# False 42\n\nprint(packet['OK'], packet['value'])\n# False 42\n```\n\nValues can also be set in the same fashion\n```python\npacket = MyPacket()\npacket[0] = True\npacket[1] = 100\n\nprint(packet['OK'], packet['value'])\n# True 100\n```\n\n#### Packing/Unpacking\nThe entire purpose of this library is to work with bytes, so it should come to no surprise that packet instances can be serialized into their raw bytes and back.\n\n```python\npacket = MyPacket()\n\nraw = b'\\x01\\x00\\x00\\x00\\xFF'\npacket.unpack(raw)\nprint(repr(packet))\n# \n# OK: True\n# value: 255\n\nraw2 = packet.pack()\nprint(raw == raw2)\n# True\n```\n\nPacket instances can be constructed directly from bytes as well using the from_raw() call\n```python\npacket = MyPacket.from_raw(b'\\x01\\x00\\x00\\x00\\xFF')\nprint(repr(packet))\n# \n# OK: True\n# value: 255\n```\n\n### Fields\nThe different components of the packet are referred to as fields, which are a collection of the associated value, meta data, and supporting functions.\n\nPacketeer comes with the following field types:\n* *fields.Padding*: (1 Byte) N/A\n* *fields.Bool*: (1 Byte) Boolean\n* *fields.Char*: (1 Byte) Character\n* *fields.Int8*: (1 Byte) Signed Integer\n* *fields.UInt8*: (1 Byte) Unsigned Integer\n* *fields.Int16*: (2 Byte) Signed Integer\n* *fields.UInt16*: (2 Byte) Unsigned Integer\n* *fields.Int32*: (4 Byte) Signed Integer\n* *fields.UInt32*: (4 Byte) Unsigned Integer\n* *fields.Int64*: (8 Byte) Signed Integer\n* *fields.UInt64*: (8 Byte) Unsigned Integer\n* *fields.Float*: (4 Byte) Float value\n* *fields.Double* (8 Byte) Float value\n* *fields.Raw*: (n Byte) Raw byte data as a single value\n* *fields.String*: (n Bytes) Unicode String as a single value\n\nThe majority of the types are self explanatory and work identically to the others, but some like padding, string, and raw behave differently and are looked at further in the following sections\n\n#### Padding\n*fields.Padding* is a special field type that is 1 byte wide per character.\n\nPadding bytes are nameless and not associated with any value; They can't be accessed, but they are counted when packing and unpacking.\n```python\nfrom packeteer import packets, fields\n\nclass PaddedPacket(packets.BigEndian):\n \"\"\" Padded \"\"\"\n fields = [\n fields.Padding(),\n fields.UInt8('value'),\n fields.Padding(default=b'\\xff')\n ]\n\npacket = PaddedPacket(value=170)\nprint(repr(packet))\n# \n# value: 170\n\nprint(packet[0])\n# 170\n\nprint(packet[1])\n# IndexError\n\nraw = packet.pack()\nprint(repr(raw))\n# '\\x00\\xAA\\xFF'\n\npacket.unpack(b'\\x00\\x7f\\xff')\nprint(repr(packet))\n# \n# value: 127\n```\n\n#### Raw data and strings\n*fields.Raw* is a raw byte store of a given size (The size argument is required). If the data is too large for the field, it will be truncated to fit. Likewise if it is too short, it will be padded with null bytes.\n\n*fields.String* is an extension of *fields.Raw* that stores it's internal value as a unicode string with the encoding of your choosing (Defaults to utf8). The internal value has any trailing null byte padding removed until it is serialized.\n\n```python\nfrom packeteer import packets, fields\n\nclass DataPacket(packets.BigEndian):\n \"\"\" Data Packet \"\"\"\n fields = [\n fields.Raw('raw', size=12),\n fields.String('string', size=12, encoding='utf8')\n ]\n\npacket = DataPacket(raw=b'Hello World', string='Hello World')\nprint(repr(packet))\n# \n# raw: b'Hello World\\x00'\n# string: u'Hellow World'\n```\n\n\n#### List fields\nThere are often times when you need to have a variable list of values in a packet (Think about a repeating set of values depending on a given count value). *fields.List* takes care of this. *fields.List* requires an additional argument of the field the list contains, with the rest of the arguments given as keywords that the underlying field type requires.\n\n```python\nfrom packeteer import packets, fields\n\nclass ListPacket(packets.BigEndian):\n \"\"\" List Packet \"\"\"\n fields = [\n fields.UInt8('count')\n fields.List('messages', fields.String, size=128),\n ]\n\nmessages = ['foo', 'bar', 'Hello World']\npacket = ListPacket(count=len(messages), messages=messages)\nprint(repr(packet))\n# \n# count: 3\n# messages: [u'foo', u'bar', u'Hello World']\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/lungdart/packeteer", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "packeteer", "package_url": "https://pypi.org/project/packeteer/", "platform": "", "project_url": "https://pypi.org/project/packeteer/", "project_urls": { "Homepage": "https://github.com/lungdart/packeteer" }, "release_url": "https://pypi.org/project/packeteer/0.4/", "requires_dist": [ "future", "six" ], "requires_python": ">=2.7.0", "summary": "Light-weight packet serializer", "version": "0.4" }, "last_serial": 4964810, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "a78b6eaa435f066a08b5c8403e8ce09a", "sha256": "ca397e300558d5e08d3632c9f8997b1d6a4f05998743c2f65613734902a31e1f" }, "downloads": -1, "filename": "packeteer-0.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a78b6eaa435f066a08b5c8403e8ce09a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 9662, "upload_time": "2019-02-21T18:43:31", "url": "https://files.pythonhosted.org/packages/f1/2c/04cdb118242ad6c7a9e84b448468252fa944417e17f1d045fd7c35e63f5d/packeteer-0.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3e536ff295051073f67485bb5aca24a3", "sha256": "3d8af9890962ef3f69668361218e4b5f73fc8d122c9f463bd0fd7006fa15b6c5" }, "downloads": -1, "filename": "packeteer-0.2.tar.gz", "has_sig": false, "md5_digest": "3e536ff295051073f67485bb5aca24a3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 12126, "upload_time": "2019-02-21T18:43:33", "url": "https://files.pythonhosted.org/packages/ad/44/016aa10f54ac56204f840c80d51d4afb742635a4ebcd7c81eee1a2d499e5/packeteer-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "63766718779d5f3503e8ccf0b41ffd8c", "sha256": "cc3f5e837bfd147e4742454315d8777c80842fa14655df08a6d3e4c1020509c7" }, "downloads": -1, "filename": "packeteer-0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "63766718779d5f3503e8ccf0b41ffd8c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 11482, "upload_time": "2019-03-12T17:51:47", "url": "https://files.pythonhosted.org/packages/f6/3a/785b97e5ed54e32d3b940dfa55363a806a5c373f5a946b1b276ab081388e/packeteer-0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "babb961530a61228e450725db410daf9", "sha256": "f17908ec30a7179224fdf4cc3be8dcbc2aff700c83752d6e1e35c0fc82142b81" }, "downloads": -1, "filename": "packeteer-0.3.tar.gz", "has_sig": false, "md5_digest": "babb961530a61228e450725db410daf9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 14478, "upload_time": "2019-03-12T17:51:49", "url": "https://files.pythonhosted.org/packages/6b/b7/89c1913307bbeb570be38324b2fc7919c141358b4f90fd6943aad1dee1f2/packeteer-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "28bf0f54104cb727e5a8ff94a2083e30", "sha256": "87306b5c3847a87b0c8989af6f4206ac60d0662ab029c89c07c42219b94c4c9e" }, "downloads": -1, "filename": "packeteer-0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "28bf0f54104cb727e5a8ff94a2083e30", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 11512, "upload_time": "2019-03-20T17:27:00", "url": "https://files.pythonhosted.org/packages/1b/1d/6b8ae4c588cb4e9d1d0c5e41253ba3f140e3138eb7e901d5ed7cb57e540b/packeteer-0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "eff1599bffae4f24b6ca6fbfca730cd6", "sha256": "cf54fc17c88e6cb337423b180baa770f404695f2b147496c8a8dbae4fe1baeb1" }, "downloads": -1, "filename": "packeteer-0.4.tar.gz", "has_sig": false, "md5_digest": "eff1599bffae4f24b6ca6fbfca730cd6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 14499, "upload_time": "2019-03-20T17:27:02", "url": "https://files.pythonhosted.org/packages/26/e1/27396ad702d4f80c130eec8bd4cdef7e466fd508935df5d4b713e1e428c0/packeteer-0.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "28bf0f54104cb727e5a8ff94a2083e30", "sha256": "87306b5c3847a87b0c8989af6f4206ac60d0662ab029c89c07c42219b94c4c9e" }, "downloads": -1, "filename": "packeteer-0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "28bf0f54104cb727e5a8ff94a2083e30", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 11512, "upload_time": "2019-03-20T17:27:00", "url": "https://files.pythonhosted.org/packages/1b/1d/6b8ae4c588cb4e9d1d0c5e41253ba3f140e3138eb7e901d5ed7cb57e540b/packeteer-0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "eff1599bffae4f24b6ca6fbfca730cd6", "sha256": "cf54fc17c88e6cb337423b180baa770f404695f2b147496c8a8dbae4fe1baeb1" }, "downloads": -1, "filename": "packeteer-0.4.tar.gz", "has_sig": false, "md5_digest": "eff1599bffae4f24b6ca6fbfca730cd6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 14499, "upload_time": "2019-03-20T17:27:02", "url": "https://files.pythonhosted.org/packages/26/e1/27396ad702d4f80c130eec8bd4cdef7e466fd508935df5d4b713e1e428c0/packeteer-0.4.tar.gz" } ] }