{ "info": { "author": "Alexander Ljungberg", "author_email": "aljungberg@slevenbits.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: POSIX", "Programming Language :: Python", "Topic :: Software Development :: Libraries" ], "description": "Hexahexacontadecimal\n====================\n\n**The most compact way to encode a number into a URL.**\n\nHexahexacontadecimal is a compact format to express a number or binary\ndata in a URL. It uses all characters allowed in a URL \u2013 the `unreserved\ncharacters `__ \u2013 making\nit the most concise way to express a positive integer in a URL.\n\nNote that ``urllib.quote`` `escapes the tilde character\n(~) `__, which is not necessary as of\nRFC3986, so if you use this on HHC data you\u2019ll waste bytes. Use the\nprovided ``hhc_url_quote`` function instead if you must. By definition\nthough HHC values don\u2019t need any URL quoting.\n\nUsage\n-----\n\n::\n\n >>> from hexahexacontadecimal import hhc, hhc_to_int\n >>> print(hhc(302231454903657293676544))\n iFsGUkO.0tsxw\n >>> print(hhc_to_int('iFsGUkO.0tsxw'))\n 302231454903657293676544\n\nHexahexacontadecimal vs Base64 in URLs\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n >>> n = 292231454903657293676544\n >>> import base64\n >>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))\n PeHmHzZFTcAAAA%3D%3D\n >>> print(hhc_url_quote(hhc(n)))\n gpE4Xoy7fw5AO\n\nBase64 vs HHC in a bad case for Base64:\n\n::\n\n >>> n = 64 ** 5 + 1\n >>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))\n QAAAAQ%3D%3D\n >>> print(hhc(n))\n ucrDZ\n\nBase64 vs HHC in a bad case for HHC:\n\n::\n\n >>> n = 66 ** 5 + 1\n >>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))\n SqUUIQ%3D%3D\n >>> print(hhc(n))\n 100001\n\nThat big SHA-512 you always wanted to write in a URL:\n\n::\n\n >>> n = 2 ** 512\n >>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))\n AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D\n >>> print(hhc(n))\n JK84xqGD9FMXPNubPghADlRhBUzlqRscC2h~8xmi99PvuQsUCIB2CHGhMUQR8FLm72.Hbbctkqi89xspay~y4\n\nMassive savings!\n\nAre the savings really significant?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you\u2019re currently doing your Base64 encoding the naive way, then yes.\nEncoding all numbers up to 100000, HHC will lead to much shorter total\nlength of URLs.\n\n::\n\n >>> sum(len(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n)))) for n in range(10 ** 5))\n 531584\n >>> sum(len(hhc_url_quote(hhc(n))) for n in range(10 ** 5))\n 295578\n\nWhat if I use Base64 without padding?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThen the savings are much less significant. Yet they are still savings.\nIf you\u2019re a perfectionist this is the kind of thing you might care\nabout.\n\nLet\u2019s test it using the code from `this StackOverFlow\nquestion `__:\n\n::\n\n >>> from hexahexacontadecimal.num_encode_base64 import num_encode as num_encode_base64\n >>> n = 64 ** 5 + 1\n >>> print(hhc_url_quote(num_encode_base64(n)))\n BAAAAB\n >>> from hexahexacontadecimal.num_encode_base64 import num_decode as num_decode_base64\n >>> num_decode_base64(hhc_url_quote(num_encode_base64(n))) == n\n True\n\n >>> print(hhc(n))\n ucrDZ\n >>> hhc_to_int(hhc(n)) == n\n True\n\n >>> n = 66 ** 5 + 1\n >>> print(hhc_url_quote(num_encode_base64(n)))\n BKpRQh\n >>> print(hhc_url_quote(hhc(n)))\n 100001\n\n >>> n = 2 ** 512\n >>> hhc_url_quote(num_encode_base64(n))\n 'EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'\n >>> print(hhc_url_quote(hhc(n)))\n JK84xqGD9FMXPNubPghADlRhBUzlqRscC2h~8xmi99PvuQsUCIB2CHGhMUQR8FLm72.Hbbctkqi89xspay~y4\n\n >>> sum(len(hhc_url_quote(num_encode_base64(n))) for n in range(10 ** 5))\n 295840\n >>> sum(len(hhc_url_quote(hhc(n))) for n in range(10 ** 5))\n 295578\n\nWhy settle for less than perfect?\n\nSorting\n~~~~~~~\n\nIf you wish to be able to sort a list of HHC values numerically there is\na variant of HHC that allows this. See ``sortable_hhc``.\n\n::\n\n >>> hhc(67) < hhc(128)\n False\n >>> sortable_hhc(67, width=2) < sortable_hhc(128, width=2)\n True\n\nNegative Numbers\n~~~~~~~~~~~~~~~~\n\nHHC expresses negative numbers by prefixing the number with ``,`` (since\nminus is taken). This is not a URL safe character so if you URL encode a\nnegative number with HHC you end up with ``%2C`` which takes up 2 extra\ncharacters. For this reason HHC is not necessarily the shortest\nrepresentation of a negative number.\n\nThe sortable variant also supports negative numbers and will yield the\nnatural sort order (small to large), like -2, -1, 0, 1, 2.\n\nInstallation\n------------\n\n::\n\n pip install hexahexacontadecimal\n\nDocumentation\n-------------\n\nThis file and docstrings.\n\nTests\n-----\n\n`Build Status `__\n\nTo run the unit tests:\n\n::\n\n nosetests --with-doctest\n\nChangelog\n---------\n\n2.2.1\n~~~~~\n\n- Fixed: pandoc accidentally required.\n\n.. _section-1:\n\n2.2\n~~~\n\n- Python 3 support (backwards compatible with Python 2.7).\n\n.. _section-2:\n\n2.1\n~~~\n\n- Fixed: ``hhc(-1)`` would cause an infinite loop.\n- New: support for negative values.\n\n.. _section-3:\n\n2.0\n~~~\n\n- New: sortable HHC. This variant of HHC sorts the same alphabetically\n as numerically for equal length strings.\n- Shorter, more Pythonic method names. The main function is now simply\n called ``hhc``, styled after Python\u2019s built in ``hex`` function. To\n decode the same, ``hhc_to_int`` is now used.\n- ``import * from hexahexacontadecimal`` now only imports the main\n functions.\n- ``urlquote`` was renamed to ``hhc_url_quote`` to make it easier to\n differentiate from the standard library method.\n\n.. _section-4:\n\n1.0\n~~~\n\nInitial release.\n\nOn the command line\n-------------------\n\nWith `pyle `__ you can easily use\nhexahexacontadecimal on the command line.\n\n::\n\n $ wc -c LICENSE MANIFEST setup.py | pyle -m hexahexacontadecimal -e \"'%-10s Hexhexconta bytes:' % words[1], hexahexacontadecimal.hhc(int(words[0]))\"\n LICENSE Hexhexconta bytes: MV\n MANIFEST Hexhexconta bytes: 1z\n setup.py Hexhexconta bytes: GI\n total Hexhexconta bytes: ei\n\nLicense\n-------\n\nFree to use and modify under the terms of the BSD open source license.\n\nAuthor\n------\n\nAlexander Ljungberg\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aljungberg/hexahexacontadecimal", "keywords": "base64,hexahexacontadecimal,hhc,base66,url", "license": "", "maintainer": "", "maintainer_email": "", "name": "hexahexacontadecimal", "package_url": "https://pypi.org/project/hexahexacontadecimal/", "platform": "", "project_url": "https://pypi.org/project/hexahexacontadecimal/", "project_urls": { "Homepage": "https://github.com/aljungberg/hexahexacontadecimal" }, "release_url": "https://pypi.org/project/hexahexacontadecimal/2.2.1/", "requires_dist": null, "requires_python": "", "summary": "The best way to express a number in a URL.", "version": "2.2.1" }, "last_serial": 4245503, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "5ba8eb3c27ce579a4eb621893d56412a", "sha256": "d9d2c589faa4bea995c64da2fa581ab1cab19fcc6a42609ed338038fe04a2440" }, "downloads": -1, "filename": "hexahexacontadecimal-1.0.tar.gz", "has_sig": false, "md5_digest": "5ba8eb3c27ce579a4eb621893d56412a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2880, "upload_time": "2013-08-01T14:39:11", "url": "https://files.pythonhosted.org/packages/65/7c/ae54ba5f4765c0ee5304604c93e4dbf474ff5125264e6ca840791951eb46/hexahexacontadecimal-1.0.tar.gz" } ], "2.0": [ { "comment_text": "", "digests": { "md5": "9f192b22fe07f2e4d4621f395a1256ff", "sha256": "b4192391aa9643a5d4681f4e20f807fcce2547d9f987d05dca3e1694cb78f2cd" }, "downloads": -1, "filename": "hexahexacontadecimal-2.0.tar.gz", "has_sig": false, "md5_digest": "9f192b22fe07f2e4d4621f395a1256ff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3783, "upload_time": "2016-07-05T11:10:24", "url": "https://files.pythonhosted.org/packages/85/4d/975d4216ffd7a2c86fa5ef20f2769f78df7c2845f3daddeaa31c82d5a6b7/hexahexacontadecimal-2.0.tar.gz" } ], "2.1": [ { "comment_text": "", "digests": { "md5": "cb55a997b1be5f58b2f50d122dc81189", "sha256": "4fc5b4ad144825597f6ea261229c94f7db8faf180969f9d6fd18786fdd0871bb" }, "downloads": -1, "filename": "hexahexacontadecimal-2.1.tar.gz", "has_sig": false, "md5_digest": "cb55a997b1be5f58b2f50d122dc81189", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4312, "upload_time": "2016-07-06T11:12:08", "url": "https://files.pythonhosted.org/packages/ef/b6/3392740bfc8ba0da9c44db8eefb81632f65a941317cd07d8f6dfa5346540/hexahexacontadecimal-2.1.tar.gz" } ], "2.2": [ { "comment_text": "", "digests": { "md5": "f49ed8e3e16fa76b15509da6a7bb3208", "sha256": "e945d19b0a22e12c7c4bce00d9c71bb061754c99fe4357a058aa822abb0625bf" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2-py3-none-any.whl", "has_sig": false, "md5_digest": "f49ed8e3e16fa76b15509da6a7bb3208", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7822, "upload_time": "2018-07-31T11:39:56", "url": "https://files.pythonhosted.org/packages/fd/18/f878cb070498291c5c43d9b37f2128d34bf8a1f8860d0a6a5518a3187c6a/hexahexacontadecimal-2.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c8aacc9aed0d560879f0d29cd1e19b1f", "sha256": "f2004dce7b397f7049a7a61ba7f1274d2c1af689a50bb540cfb9ee4ae79e8c32" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2.tar.gz", "has_sig": false, "md5_digest": "c8aacc9aed0d560879f0d29cd1e19b1f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6441, "upload_time": "2018-07-31T11:39:58", "url": "https://files.pythonhosted.org/packages/eb/14/1d72ec5704a19dd42cb64ee3d85f3070c3b2836529e0ca0c69190a429fcf/hexahexacontadecimal-2.2.tar.gz" } ], "2.2.1": [ { "comment_text": "", "digests": { "md5": "cae690f99836ee33f4d21f9c1ae81429", "sha256": "6d0f14b00989014c53e0b8de8e5377b6c2e1da43d943b31652d96ae0a9ef6593" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "cae690f99836ee33f4d21f9c1ae81429", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7854, "upload_time": "2018-09-06T17:05:57", "url": "https://files.pythonhosted.org/packages/3b/ab/6182b652e1b1f00b54cea12e18e215928c65fa1f9f1e5ed5ba338e7984ea/hexahexacontadecimal-2.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "75265675041b67b2de1dcd661da160d5", "sha256": "7b7567c6d9198ffe01aa144cb31479d06d4b4c51e2d2976a80a35e6a6fd3f8d2" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2.1.tar.gz", "has_sig": false, "md5_digest": "75265675041b67b2de1dcd661da160d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6507, "upload_time": "2018-09-06T17:06:00", "url": "https://files.pythonhosted.org/packages/6e/49/a36173a2f14b8a51331f9527394b112773feee683ef6a5dff4f4091ebcae/hexahexacontadecimal-2.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "cae690f99836ee33f4d21f9c1ae81429", "sha256": "6d0f14b00989014c53e0b8de8e5377b6c2e1da43d943b31652d96ae0a9ef6593" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "cae690f99836ee33f4d21f9c1ae81429", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7854, "upload_time": "2018-09-06T17:05:57", "url": "https://files.pythonhosted.org/packages/3b/ab/6182b652e1b1f00b54cea12e18e215928c65fa1f9f1e5ed5ba338e7984ea/hexahexacontadecimal-2.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "75265675041b67b2de1dcd661da160d5", "sha256": "7b7567c6d9198ffe01aa144cb31479d06d4b4c51e2d2976a80a35e6a6fd3f8d2" }, "downloads": -1, "filename": "hexahexacontadecimal-2.2.1.tar.gz", "has_sig": false, "md5_digest": "75265675041b67b2de1dcd661da160d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6507, "upload_time": "2018-09-06T17:06:00", "url": "https://files.pythonhosted.org/packages/6e/49/a36173a2f14b8a51331f9527394b112773feee683ef6a5dff4f4091ebcae/hexahexacontadecimal-2.2.1.tar.gz" } ] }