{ "info": { "author": "Gilad Naaman", "author_email": "gilad@naaman.io", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3" ], "description": "# Hydras #\n[![Build Status](https://travis-ci.org/Gilnaa/Hydras.svg?branch=master)](https://travis-ci.org/Gilnaa/Hydras)\n\n'*Hydras*' is a python library that allows the developer to create structured binary data according to simple rules,\nsomewhat similar to how C does it with a struct.\n\nWhy \"Hydras\"? `Hydra` was taken.\n\n\n## Example ##\n```python\nclass Header(Struct):\n Opcode = uint8_t(4) # The `opcode`'s default value will now be `4`\n DataLength = uint32_t()\n\nclass DataPacket(Struct):\n # A nested structure. \"DataLength = 128\" sets the default DataLength value for `Header`s inside `DataPacket`s\n Header = Header(DataLength=128)\n # Creates an array of bytes with a length of 128 bytes.\n Payload = Array(length = 128)\n\n # To override the constructor it must be able to override the default ctor (1 argument)\n def __init__(self, opcode=0):\n # Must call the base ctor\n super(DataPacket, self).__init__()\n self.Header.Opcode = opcode\n\nif __name__ == '__main__':\n packet = DataPacket()\n # After you create the object, you can ignore the formatting rules, and assign the data directly to the properties.\n packet.Header.Opcode = DATAPACKET_OPCODE\n\n # You can transform the object into a byte string using the `serialize` method.\n data_to_send = packet.serialize() # => b'\\x04\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00...'\n some_socket.send(data_to_send)\n\n packet.Payload = '\\xFF' * 128\n data_to_send = packet.serialize() # => b'\\x04\\x80\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF...'\n\n # . . .\n\n # You can parse raw byte strings into an object using the deserialize class method.\n received_data = some_socket.recv(len(packet))\n parsed_packet = DataPacket.deserialize(received_data)\n```\n\nYou can find more examples in the examples directory.\n\n## How does it work? ##\nIn the core of the library, there are two types of objects: `TypeFormatter` and `Struct`.\n\n`TypeFormatter` is a formatting object, and can parse and format values of a specified type.\n`Struct` is a structure object, which enables you to define rules for object serialization.\n\nThe developer can thus declare a class using the following notation:\n```python\nclass (Struct):\n = ()\n```\nor\n```python\nclass Message(Struct):\n TimeOfDay = uint64_t # This creates a u64 formatter. Parentheses are optional.\n DataLength = uint8_t(128) # A default value is optional\n\nMessage().serialize() #=> b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80'\n```\n\nThe declared data members are in fact (due to python's syntax), static.\nWhen a class object is created, the constructor (deep) copies each of the formatters' `default_value`s into an instance variable in the same name,\nso some transparency is achieved by \"tricking\" the user into thinking no formatters are involved:\n```\nClass members:\n TimeOfDay: uint64_t (default_value = 0)\n DataLength: uint8_t (default_value = 128)\nObject members:\n TimeOfDay: 0\n DataLength: 128\n```\n\nWhen the object is serialized, the object's data is cross-referenced with the class's formatters.\nAll of the integers are internally converted using python's `struct.pack` function.\n\n## Validators ##\nA validator object can be assigned to a struct data member to define validation rules.\nWhen deserializing an object from binary data, the framework will validate the values\nusing the user-defined validation-rules.\n\nIf an invalid value is encountered, a ValueError is raised.\n\n```python\nclass MeIsValidated(Struct):\n member = int8_t(0, validator=RangeValidator(-15, 15))\n\n...\n\nMeIsValidated.deserialize('\\x10') # => ValueError: The deserialized data is invalid.\n```\n\nThere are a few built-in validators defined for the following rules:\n - RangeValidator: Range check\n - ExactValueValidator: Exact value check\n - BitSizeValidator: Bit-Length check\n - CustomValidator: Lambda validation (receives a user function.)\n - TrueValidator & FalseValidator: Dummy validators (always true / always false)\n\nMore validators can be defined by subclassing the Validator class.\n\n### Lambda Validators ###\nThe user can use a lambda expression (or any function) instead of a validator object as validation rule.\n\n```python\nclass MeIsLambda(Struct):\n member = int8_t(0, validator=lambda value: value % 3 == 0)\n```\n\n## Hooks ##\nA `Struct` derived class can implement hooks.\n### before_serialize ###\nThis method will be called before a serialization is about to occur.\n\n**Note**: This method will not be called if either `HydraSettings.dry_run` is True,\nor `serialize` is called with `dry_run=True`\n\n### after_serialize ###\nThis method will be called after a serialization has occurd.\n\n**Note**: This method will not be called if either `HydraSettings.dry_run` is True,\nor `serialize` is called with `dry_run=True`\n\n### validate ###\nCalled after a de-serialization is completed.\nIf it returns a `False`y value, the `deserialize` raises an error.\n\nIf not overriden by the user in a custom Struct class, the method\nwill validate using the type formatters' validators.\n\nThe user can, of course, override the method to add custom validations,\nand then invoke the original validate method.\n\n**Note**: No errors will be raised if `HydraSettings.validate` is set to `False`.\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/Gilnaa/Hydras", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "Hydras", "package_url": "https://pypi.org/project/Hydras/", "platform": "", "project_url": "https://pypi.org/project/Hydras/", "project_urls": { "Homepage": "https://github.com/Gilnaa/Hydras" }, "release_url": "https://pypi.org/project/Hydras/2.0.1/", "requires_dist": null, "requires_python": "", "summary": "A module for constructions of structured binary packets.", "version": "2.0.1" }, "last_serial": 5981406, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "2967055598659e77b335fda01c0acb9b", "sha256": "a1ff819a1fe04aa4f45ece5c042181306eb687bc36920669f10d5785c654159b" }, "downloads": -1, "filename": "Hydras-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "2967055598659e77b335fda01c0acb9b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22307, "upload_time": "2019-05-10T15:06:36", "url": "https://files.pythonhosted.org/packages/0f/eb/e8e8bc59cec310469da2b2c0b489a06acd430019087c5279e262b2b04ba6/Hydras-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "26842aa8cebd26ff5e6fe87232e17dd9", "sha256": "dea08c9cda7764307f101ff2c4d9f22d0b74b53a97d55ac66b5ca4c188284e6d" }, "downloads": -1, "filename": "Hydras-1.0.0.tar.gz", "has_sig": false, "md5_digest": "26842aa8cebd26ff5e6fe87232e17dd9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16151, "upload_time": "2019-05-10T15:06:38", "url": "https://files.pythonhosted.org/packages/0b/28/314289cfa37b020c0623bd2e30da699dc6158fa43450502f1b5fbc555d5b/Hydras-1.0.0.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "4b1a4e4653866983ba8321f4971ae74d", "sha256": "88cd93b7ba0694cb1da4b4e4756fd9c457d5bd73e6edfeb1b3a0bc4d03d3fa86" }, "downloads": -1, "filename": "Hydras-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4b1a4e4653866983ba8321f4971ae74d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22135, "upload_time": "2019-10-14T16:07:22", "url": "https://files.pythonhosted.org/packages/b8/ac/4c523bbc02efbfdb9da4747f73742fe8d2dfc764a38ffb40126d0add17d2/Hydras-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c59111aa899eb459f7ef683dfe6d2d0c", "sha256": "6ec89fab6d99db15319abb6dee6229d76f05e46b5cf1c7775485bef939be8f6a" }, "downloads": -1, "filename": "Hydras-2.0.0.tar.gz", "has_sig": false, "md5_digest": "c59111aa899eb459f7ef683dfe6d2d0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16277, "upload_time": "2019-10-14T16:07:24", "url": "https://files.pythonhosted.org/packages/c5/dc/fde418a8938cd5156d75c2c1950e734ddb784b0aa8105156c9653c3cbf33/Hydras-2.0.0.tar.gz" } ], "2.0.1": [ { "comment_text": "", "digests": { "md5": "a323b0dfdb3aeccd4a2c743d24fafa40", "sha256": "e11ec959f1c629603aa16b280c2b689258eecc97628831c251feb532638fec78" }, "downloads": -1, "filename": "Hydras-2.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a323b0dfdb3aeccd4a2c743d24fafa40", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22139, "upload_time": "2019-10-16T05:49:39", "url": "https://files.pythonhosted.org/packages/93/cc/ccb8b7f1fdf53025ec9aed3cc701a282aed4efed539e47868835d855e952/Hydras-2.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ec7136e0de1802bef8557ea83a68852c", "sha256": "2d99c13452909b1ad805285e404914918709b2a6d00e62e8f96eeaa101ab1a8e" }, "downloads": -1, "filename": "Hydras-2.0.1.tar.gz", "has_sig": false, "md5_digest": "ec7136e0de1802bef8557ea83a68852c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16286, "upload_time": "2019-10-16T05:49:40", "url": "https://files.pythonhosted.org/packages/37/f2/28d042b550cd255b8a05242cabc64e47680cedb8791947f81684082e8019/Hydras-2.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a323b0dfdb3aeccd4a2c743d24fafa40", "sha256": "e11ec959f1c629603aa16b280c2b689258eecc97628831c251feb532638fec78" }, "downloads": -1, "filename": "Hydras-2.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a323b0dfdb3aeccd4a2c743d24fafa40", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22139, "upload_time": "2019-10-16T05:49:39", "url": "https://files.pythonhosted.org/packages/93/cc/ccb8b7f1fdf53025ec9aed3cc701a282aed4efed539e47868835d855e952/Hydras-2.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ec7136e0de1802bef8557ea83a68852c", "sha256": "2d99c13452909b1ad805285e404914918709b2a6d00e62e8f96eeaa101ab1a8e" }, "downloads": -1, "filename": "Hydras-2.0.1.tar.gz", "has_sig": false, "md5_digest": "ec7136e0de1802bef8557ea83a68852c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16286, "upload_time": "2019-10-16T05:49:40", "url": "https://files.pythonhosted.org/packages/37/f2/28d042b550cd255b8a05242cabc64e47680cedb8791947f81684082e8019/Hydras-2.0.1.tar.gz" } ] }