{ "info": { "author": "Joshua Saxby", "author_email": "joshua.a.saxby@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "Intended Audience :: Telecommunications Industry", "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", "Operating System :: OS Independent", "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", "Topic :: Communications", "Topic :: Education", "Topic :: Internet", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "# basest-python\nArbitrary base binary-to-text encoder (any base to any base), in Python.\n\n## What?\nIn short, **basest** is *based on* (pun *definitely* intended :wink:) the concept of binary-to-text conversion, that is where binary or 8-bit data is converted or serialised into a text-based representation format that can be safely passed through a medium that would otherwise destroy or corrupt the meaning of the binary data.\n\nThis concept is very commonly used in areas such as Email, the PDF format and Public Key Cryptography, to name but a few.\n\nThere are many different formats and schemes for serilising binary data to text, employing different alphabet sizes and different printable ASCII characters used for various different reasons.\n\nIt is also not just 8-bit binary data that could be serialised. Any collection of symbols declared to be in a given number base or alphabet size can be serialised into any other, provided an encoding ratio between the two symbols can be established and the input and output symbols defined.\n\nThis library is my implementation of a generic, base-to-base converter which addresses this last point. An encoder and decoder for every binary-to-text format currently existing can be created and used with this library, requiring only for the details of the desired format to be given. Due to its flexibility, the library also makes it trivial to invent new wonderful and interesting base-to-base serialisation/conversion formats (I myself plan to work on and release one that translates binary files into a purely emoji-based format!).\n\nOne limitation of the library is that it cannot encode data from a smaller input base to a larger output base with padding on the input (i.e. if you're encoding from base 2 to base 1000, you need to ensure that the number of input symbols exactly matches the encoding ratio you're using). This is an accepted limitation due to the complexities of implementing a padding system that works in the same manner as base-64 and others but which can be extended to any arbitrary base.\n\nSo, I hope you find this library fun, useful or both!\n\n## Installation\n\n#### Python Versions Supported\nThis library is designed to work with **Python 2.7** and **Python 3.3 _or greater_**.\n\nIt is tested against Python **2.7**, **3.5**, **3.6** and **PyPy 3.5**.\n\n> :bulb: **Help Wanted**\n>\n> If you have tried or want to try this out on any other Python implementations, your feedback would be greatly appreciated!\n>\n> [Open an issue](https://github.com/saxbophone/basest-python/issues) if you are interested.\n\n#### Install from PyPi (preferred)\n\n`pip install basest`\n\n#### Install from git repository (bleeding edge copy from develop branch)\n`pip install git+git://github.com/saxbophone/basest-python@develop`\n\n## Usage\nHere is a short overview of the interfaces defined in this library, where to import them from and how to use them.\n\nThere is a functional interface and a class-based interface (the class-based one piggy-backs on the functional one, but will also be used to add additional features in the future).\n\n### Class-based Interface\n\nTo use the class-based interface, you will need to create a subclass of `basest.encoders.Encoder` and override attributes of the class, as shown below (using base64 as an example):\n\n```py\nfrom basest.encoders import Encoder\n\nclass CustomEncoder(Encoder):\n input_base = 256\n output_base = 64\n input_ratio = 3\n output_ratio = 4\n # these attributes are only required if using decode() and encode()\n input_symbol_table = [chr(c) for c in range(256)]\n output_symbol_table = [\n s for s in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n ]\n padding_symbol = '='\n\n```\n\n> **Note:** You must subclass `Encoder`, you cannot use it directly!\n\nSubclasses of `Encoder` have the following public methods available:\n\n#### Encode from one base to another\n`encode()` will encode an iterable of symbols in the class' **input symbol table** into an iterable of symbols in the class' **output symbol table**, observing the chosen encoding ratios and padding symbol.\n\n```py\nencoder = CustomEncoder()\nencoder.encode(['c', 'a', 'b', 'b', 'a', 'g', 'e', 's'])\n# -> ['Y', '2', 'F', 'i', 'Y', 'm', 'F', 'n', 'Z', 'X', 'M', '=']\n```\n\n#### Encode Raw\n`encode_raw()` works just like `encode()`, except that symbols are not interpreted. Instead, plain integers within range 0->(base - 1) should be used. the value of the base is used as the padding symbol.\n\n```py\nencoder = CustomEncoder()\nencoder.encode_raw([1, 2, 3, 4, 5, 6, 7])\n# -> [0, 16, 8, 3, 1, 0, 20, 6, 1, 48, 64, 64]\n```\n\n#### Decode from one base to another\n`decode()` works in the exact same way as `encode()`, but in the inverse.\n\n```py\nencoder = CustomEncoder()\nencoder.decode(['Y', '2', 'F', 'i', 'Y', 'm', 'F', 'n', 'Z', 'X', 'M', '='])\n# -> ['c', 'a', 'b', 'b', 'a', 'g', 'e', 's']\n```\n\n#### Decode Raw\n`decode_raw()` works just like `decode()`, except that symbols are not interpreted. Instead, plain integers within range 0->(base - 1) should be used. the value of the base is used as the padding symbol.\n\n```py\nencoder = CustomEncoder()\nencoder.decode_raw([0, 16, 8, 3, 1, 0, 20, 6, 1, 48, 64, 64])\n# -> [1, 2, 3, 4, 5, 6, 7]\n```\n\n### Functional Interface\n\n#### Encode from one base to another (where the encoding ratios to use are known)\nFor a given **input base**, **input symbol table**, **output base**, **output symbol table**, **output padding**, **input ratio**, **output ratio** and the **input data** (as an iterable composed of items which are defined in **input symbol table**):\nReturn the input data, encoded into the specified base using the specified encoding ratio and symbol tables (and the supplied **output padding** symbol used if needed).\nReturns the output data as a list of items that are guaranteed to be in the **output symbol table**, or the **output padding** symbol.\n\n```py\nimport basest\n\nbasest.core.encode(\n input_base=256,\n input_symbol_table=[chr(c) for c in range(256)],\n output_base=64,\n output_symbol_table=[\n s for s in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n ],\n output_padding='=', input_ratio=3, output_ratio=4,\n input_data='falafel'\n)\n# -> ['Z', 'm', 'F', 's', 'Y', 'W', 'Z', 'l', 'b', 'A', '=', '=']\n```\n\n#### Encode Raw\nSimilar to the function above, `basest.core.encode_raw` will encode one base into another, but only accepts and returns arrays of integers (e.g. bytes would be passed as integers between 0-255, not as `byte` objects). As such, it omits the **padding** and **symbol table** arguments, but is otherwise identical in function and form to `encode`.\n\n```py\nimport basest\n\nbasest.core.encode_raw(\n input_base=256, output_base=85,\n input_ratio=4, output_ratio=5,\n input_data=[99, 97, 98, 98, 97, 103, 101, 115]\n)\n# -> [31, 79, 81, 71, 52, 31, 25, 82, 13, 76]\n```\n\n#### Decode from one encoded base to another.\nFor a given **input base**, **input symbol table**, **input padding**, **output base**, **output symbol table**, **input ratio**, **output ratio** and the **input data** (as an iterable composed of items which are defined in **input symbol table**), return the input data, decoded from the base it was encoded into.\nReturns the output data as a list of items that are guaranteed to be in the **output symbol table**, with no padding.\n\n> This is essentially the inverse of `encode()`\n\n```py\nimport basest\n\nbasest.core.decode(\n input_base=64,\n input_symbol_table=[\n s for s in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n ],\n input_padding='=',\n output_base=256, output_symbol_table=[chr(c) for c in range(256)],\n input_ratio=4, output_ratio=3,\n input_data='YWJhY3VzIFpaWg=='\n)\n# -> ['a', 'b', 'a', 'c', 'u', 's', ' ', 'Z', 'Z', 'Z']\n```\n\n#### Decode Raw\nSimilar to the function above, `basest.core.decode_raw` will decode from one base to another, but only accepts and returns arrays of integers (e.g. base64 would be passed as integers between 0-65 (65 is for the padding symbol), not as `str` objects). As such, it omits the **padding** and **symbol table** arguments, but is otherwise identical in function and form to `decode`.\n\n```py\nimport basest\n\nbasest.core.decode_raw(\n input_base=85, output_base=256,\n input_ratio=5, output_ratio=4,\n input_data=[31, 79, 81, 71, 52, 31, 25, 82, 13, 76]\n)\n# -> [99, 97, 98, 98, 97, 103, 101, 115]\n```\n\n#### Finding the best encoding ratio from one base to any base within a given range\nFor a given **input base** (e.g. base-256 / 8-bit Bytes), a given desired **output base** (e.g. base 94) **OR** a given range of acceptable **output bases** and a range of **chunk sizes** to consider using for the input (amount of bytes/symbols processed at once), return the most efficient output base and encoding ratio to use (in terms of input base to output base).\n\nReturns tuples containing an integer as the first item (representing the output base that is most efficient) and a tuple as the second, containing two integers representing the ratio of **input base** symbols to **output base** symbols.\n\n```py\nimport basest\n\nbasest.core.best_ratio(input_base=256, output_bases=[94], chunk_sizes=range(1, 256))\n# -> (94, (68, 83))\nbasest.core.best_ratio(input_base=256, output_bases=[94], chunk_sizes=range(1, 512))\n# -> (94, (458, 559))\nbasest.core.best_ratio(input_base=256, output_bases=range(2, 95), chunk_sizes=range(1, 256))\n# -> (94, (68, 83))\nbasest.core.best_ratio(input_base=256, output_bases=range(2, 334), chunk_sizes=range(1, 256))\n# -> (333, (243, 232))\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/saxbophone/basest-python", "keywords": "number base encoder decoder conversion encoding decoding", "license": "", "maintainer": "", "maintainer_email": "", "name": "basest", "package_url": "https://pypi.org/project/basest/", "platform": "", "project_url": "https://pypi.org/project/basest/", "project_urls": { "Homepage": "https://github.com/saxbophone/basest-python" }, "release_url": "https://pypi.org/project/basest/0.7.3/", "requires_dist": null, "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "summary": "Arbitrary base binary-to-text encoder (any base to any base)", "version": "0.7.3" }, "last_serial": 4445932, "releases": { "0.7.1": [ { "comment_text": "", "digests": { "md5": "0cc3e6f5bd593c1b76ce1d99f234ecd6", "sha256": "3d7d1fa139e374a21ba4155afd0304bd1669ef428ceeb4d5c0736f0f2aefabc1" }, "downloads": -1, "filename": "basest-0.7.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0cc3e6f5bd593c1b76ce1d99f234ecd6", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28465, "upload_time": "2018-10-31T22:37:35", "url": "https://files.pythonhosted.org/packages/15/06/45b1794bf32a5c06cab35f7c9d4852dc1db09cc5730fbf6169e39af5ff00/basest-0.7.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5937ad51c9e147cbc3671ecc9dcf5986", "sha256": "f882a9acb01644a73dca78368c10bfd9b386b5c8c378ce54853dbfbe520a3486" }, "downloads": -1, "filename": "basest-0.7.1.tar.gz", "has_sig": false, "md5_digest": "5937ad51c9e147cbc3671ecc9dcf5986", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20655, "upload_time": "2018-10-31T22:37:37", "url": "https://files.pythonhosted.org/packages/b1/cd/b3122497252117b5828425176b8b8ed96bac17ace0561ddad4f7f5d70610/basest-0.7.1.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "52f90b04c135ba53186bf1e34f7bb6c8", "sha256": "53d4c0fd263ad670b998ae9e96ae35235e62a8b65e11583b3335513e14d81cfd" }, "downloads": -1, "filename": "basest-0.7.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "52f90b04c135ba53186bf1e34f7bb6c8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28466, "upload_time": "2018-11-01T12:32:00", "url": "https://files.pythonhosted.org/packages/f8/f2/11f41435ad59171f7a210cf45e56a46f7dc141723386223e848b629ddbee/basest-0.7.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "13d203e95d3a8e4e1b4a712c30b01f10", "sha256": "35508236a580bc2e8da23a84d2c0bdeb5eb70108b265c1e6b30e21399f0d23fe" }, "downloads": -1, "filename": "basest-0.7.2.tar.gz", "has_sig": false, "md5_digest": "13d203e95d3a8e4e1b4a712c30b01f10", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20493, "upload_time": "2018-11-01T12:32:04", "url": "https://files.pythonhosted.org/packages/ee/87/7fdc2e698189f335ee3cdcf6a2e6499c25628402cc9cc1d716a25e81525d/basest-0.7.2.tar.gz" } ], "0.7.2.dev1": [ { "comment_text": "", "digests": { "md5": "da702350b0f05fd9fe264acc86c8b1bd", "sha256": "2e85700f48e9d7036bb6b2265add530597f076beb5b28b3ca7517953601d295f" }, "downloads": -1, "filename": "basest-0.7.2.dev1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "da702350b0f05fd9fe264acc86c8b1bd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28527, "upload_time": "2018-11-01T12:21:36", "url": "https://files.pythonhosted.org/packages/a2/d7/77724451c8f0ee2f995db1d3c4a9d70c1131fe9a7e5b057893f191faa3e2/basest-0.7.2.dev1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b1cb86c735dfcf20a7ad152523792388", "sha256": "d3425984163d069b305240a320223b9b2e23415744eff9669f21f4691fdfa365" }, "downloads": -1, "filename": "basest-0.7.2.dev1.tar.gz", "has_sig": false, "md5_digest": "b1cb86c735dfcf20a7ad152523792388", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20490, "upload_time": "2018-11-01T12:21:38", "url": "https://files.pythonhosted.org/packages/16/a6/fc3fc240a75edd2f6d3a476b159626b3df7ae9f29ea145fc5355ef19fc03/basest-0.7.2.dev1.tar.gz" } ], "0.7.3": [ { "comment_text": "", "digests": { "md5": "40d7d8ac2e2e625692d400627d44f087", "sha256": "77449eaa031182a205c69811d341830a16a9d9e258e10fd5504b89b23ad8066f" }, "downloads": -1, "filename": "basest-0.7.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "40d7d8ac2e2e625692d400627d44f087", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 27719, "upload_time": "2018-11-02T20:02:18", "url": "https://files.pythonhosted.org/packages/de/ac/35db43f6fbb209d3c62c980ef27a035f4ef284a4a0f35fb0e16182a40c0a/basest-0.7.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a4aeeebc78b62a56b27a1b003c6455a5", "sha256": "57468bcff59306dde1943fb3e3839aafd8f9e11ad29909e4768b93e8bdf213a9" }, "downloads": -1, "filename": "basest-0.7.3.tar.gz", "has_sig": false, "md5_digest": "a4aeeebc78b62a56b27a1b003c6455a5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 20266, "upload_time": "2018-11-02T20:02:19", "url": "https://files.pythonhosted.org/packages/20/20/71a16aa9ec3c307ae4086fbd9cfd43403fe7a833e50a5a274be14c156ea2/basest-0.7.3.tar.gz" } ], "0.7.3.dev1": [ { "comment_text": "", "digests": { "md5": "d4c2af9d10a48082d987d0ca0442f837", "sha256": "6c9779898013dd7a59cf47f4451a4925b0ae705ddc8a1d5189e155e5ae1ef7ee" }, "downloads": -1, "filename": "basest-0.7.3.dev1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d4c2af9d10a48082d987d0ca0442f837", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 27818, "upload_time": "2018-11-02T16:24:44", "url": "https://files.pythonhosted.org/packages/71/fb/32f35013eb9c302a55679197ce1764cad49cfda5bde9a29fdc5bfe140ab7/basest-0.7.3.dev1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5da9ef34a60a17cfe09bbf2b4f91d961", "sha256": "75b731bf30b50a10aaa3bee60cd7f8248045fab60b7a8fb1a707093b035f758e" }, "downloads": -1, "filename": "basest-0.7.3.dev1.tar.gz", "has_sig": false, "md5_digest": "5da9ef34a60a17cfe09bbf2b4f91d961", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 20278, "upload_time": "2018-11-02T16:24:45", "url": "https://files.pythonhosted.org/packages/b2/29/6bb6ab9201b460165f55c13f0cdd6f9b32a587fa263561278956499ab921/basest-0.7.3.dev1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "40d7d8ac2e2e625692d400627d44f087", "sha256": "77449eaa031182a205c69811d341830a16a9d9e258e10fd5504b89b23ad8066f" }, "downloads": -1, "filename": "basest-0.7.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "40d7d8ac2e2e625692d400627d44f087", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 27719, "upload_time": "2018-11-02T20:02:18", "url": "https://files.pythonhosted.org/packages/de/ac/35db43f6fbb209d3c62c980ef27a035f4ef284a4a0f35fb0e16182a40c0a/basest-0.7.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a4aeeebc78b62a56b27a1b003c6455a5", "sha256": "57468bcff59306dde1943fb3e3839aafd8f9e11ad29909e4768b93e8bdf213a9" }, "downloads": -1, "filename": "basest-0.7.3.tar.gz", "has_sig": false, "md5_digest": "a4aeeebc78b62a56b27a1b003c6455a5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*", "size": 20266, "upload_time": "2018-11-02T20:02:19", "url": "https://files.pythonhosted.org/packages/20/20/71a16aa9ec3c307ae4086fbd9cfd43403fe7a833e50a5a274be14c156ea2/basest-0.7.3.tar.gz" } ] }