├── .gitignore ├── LICENSE ├── README.md ├── fuuid └── __init__.py └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Phil Demetriou 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🏷️ fuuid 2 | 3 | FUUID stands for Functional Universally Unique IDentifier. FUUIDs are compatible with regular UUIDs but are naturally ordered by generation time, collision-free and support succinct representations such as raw binary and base58-encoded strings. 4 | 5 | In short, running FUUIDs through the UNIX sort command will result in a list ordered by generation time. 6 | 7 | # Installation 8 | 9 | You can install this package using `pip` or build it from source using `poetry`: 10 | 11 | # Using pip 12 | pip install fuuid 13 | 14 | # Using poetry 15 | pip install poetry 16 | poetry build 17 | 18 | # Example 19 | 20 | ```python 21 | from fuuid import fuuid, fuuid_ns, raw_fuuid, raw_fuuid_ns, b58_fuuid, b58_fuuid_ns, b64_fuuid, b64_fuuid_ns 22 | 23 | fuuid() 24 | # UUID('01324332-f66a-054a-76e4-fbdc7f772cd1') 25 | 26 | fuuid_ns() 27 | # UUID('00474eaa-b5d8-3844-338c-e77ecd424b06') 28 | 29 | raw_fuuid() 30 | # b'\x012C2\xc5\xfc\x18\xca\x96N\xe5_\xaaU86' 31 | 32 | raw_fuuid_ns() 33 | # b'\x00GN\xaa\xb5\xd88D\xfb\xfe%\xcf_\x90\xb8\xa8' 34 | 35 | b58_fuuid() 36 | # 9ZxgTVssa99BdQF3n5tSj 37 | 38 | b58_fuuid_ns() 39 | # 12zi36Vm1zaBQmpmpZ2xXk 40 | 41 | b64_fuuid() 42 | # ATJDMhbpQxNUfC7BL3F3kQ== 43 | 44 | b64_fuuid_ns() 45 | # AEdOqrXYOES+VjlfTHElKw== 46 | ``` 47 | 48 | # License 49 | ```text 50 | BSD 3-Clause License 51 | 52 | Copyright (c) 2021, Phil Demetriou 53 | All rights reserved. 54 | 55 | Redistribution and use in source and binary forms, with or without 56 | modification, are permitted provided that the following conditions are met: 57 | 58 | * Redistributions of source code must retain the above copyright notice, this 59 | list of conditions and the following disclaimer. 60 | 61 | * Redistributions in binary form must reproduce the above copyright notice, 62 | this list of conditions and the following disclaimer in the documentation 63 | and/or other materials provided with the distribution. 64 | 65 | * Neither the name of the copyright holder nor the names of its 66 | contributors may be used to endorse or promote products derived from 67 | this software without specific prior written permission. 68 | 69 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 70 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 71 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 72 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 73 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 74 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 75 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 76 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 77 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 78 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79 | ``` -------------------------------------------------------------------------------- /fuuid/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uuid 3 | from base64 import b64encode 4 | from time import time, time_ns 5 | 6 | from base58 import b58encode 7 | 8 | __all__ = ["raw_fuuid", "raw_fuuid_ns", "b58_fuuid", "b58_fuuid_ns", "b64_fuuid", "b64_fuuid_ns", "fuuid", "fuuid_ns"] 9 | 10 | 11 | def raw_fuuid(): 12 | ts = int(time() - 16 * 10 ** 8) 13 | return ts.to_bytes(4, "big") + os.urandom(12) 14 | 15 | 16 | def raw_fuuid_ns(): 17 | ts = int(time_ns() - 16 * 10 ** 17) 18 | return ts.to_bytes(8, "big") + os.urandom(8) 19 | 20 | 21 | def b58_fuuid(): 22 | return b58encode(raw_fuuid()).decode() 23 | 24 | 25 | def b58_fuuid_ns(): 26 | return b58encode(raw_fuuid_ns()).decode() 27 | 28 | 29 | def b64_fuuid(): 30 | return b64encode(raw_fuuid()).decode() 31 | 32 | 33 | def b64_fuuid_ns(): 34 | return b64encode(raw_fuuid_ns()).decode() 35 | 36 | 37 | def fuuid(): 38 | return uuid.UUID(bytes=raw_fuuid()) 39 | 40 | 41 | def fuuid_ns(): 42 | return uuid.UUID(bytes=raw_fuuid_ns()) 43 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fuuid" 3 | version = "0.1.0" 4 | description = "Functional UUIDs for Python." 5 | authors = ["Phil Demetriou "] 6 | readme = "README.md" 7 | license = "BSD-3-Clause" 8 | packages = [{ include = "fuuid" }] 9 | repository = "https://github.com/kpdemetriou/fuuid" 10 | classifiers = [ 11 | "Development Status :: 4 - Beta", 12 | "Intended Audience :: Developers", 13 | "Intended Audience :: Science/Research", 14 | "Intended Audience :: System Administrators", 15 | "Intended Audience :: Telecommunications Industry", 16 | "License :: OSI Approved :: BSD License", 17 | "Programming Language :: C", 18 | "Programming Language :: Python :: 3", 19 | "Programming Language :: Python :: 3 :: Only", 20 | "Topic :: Security", 21 | "Topic :: Security :: Cryptography", 22 | "Topic :: Utilities", 23 | ] 24 | 25 | 26 | [tool.poetry.dependencies] 27 | python = "^3.7" 28 | base58 = "^2.1.0" 29 | 30 | [tool.poetry.dev-dependencies] 31 | 32 | [build-system] 33 | requires = ["poetry-core>=1.0.0"] 34 | build-backend = "poetry.core.masonry.api" 35 | --------------------------------------------------------------------------------