typeid-python
Advanced tools
+21
| MIT License | ||
| Copyright (c) 2025 Murad Akhundov | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+237
| Metadata-Version: 2.4 | ||
| Name: typeid-python | ||
| Version: 0.3.7 | ||
| Classifier: Development Status :: 3 - Alpha | ||
| Classifier: License :: OSI Approved :: MIT License | ||
| Classifier: Programming Language :: Python :: 3.10 | ||
| Classifier: Programming Language :: Python :: 3.11 | ||
| Classifier: Programming Language :: Python :: 3.12 | ||
| Classifier: Programming Language :: Python :: 3.13 | ||
| Classifier: Programming Language :: Python :: 3.14 | ||
| Classifier: Operating System :: OS Independent | ||
| Requires-Dist: uuid-utils>=0.12.0 | ||
| Requires-Dist: click ; extra == 'cli' | ||
| Requires-Dist: pyyaml ; extra == 'yaml' | ||
| Provides-Extra: cli | ||
| Provides-Extra: yaml | ||
| License-File: LICENSE | ||
| Summary: Python implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs | ||
| Keywords: typeid,uuid,rust,guid,uuid7 | ||
| Author-email: Murad Akhundov <akhundov1murad@gmail.com> | ||
| Requires-Python: >=3.10, <4 | ||
| Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM | ||
| Project-URL: Homepage, https://github.com/akhundMurad/typeid-python | ||
| Project-URL: Repository, https://github.com/akhundMurad/typeid-python | ||
| Project-URL: Bug Tracker, https://github.com/akhundMurad/typeid-python/issues | ||
| # TypeID Python | ||
| [](https://github.com/akhundMurad/typeid-python/actions/workflows/test.yml) | ||
| [](https://pepy.tech/projects/typeid-python) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| A **high-performance Python implementation of [TypeIDs](https://github.com/jetpack-io/typeid)** — type-safe, | ||
| sortable identifiers based on **UUIDv7**. | ||
| TypeIDs are designed for modern systems where identifiers should be: | ||
| - globally unique | ||
| - sortable by creation time | ||
| - safe to expose externally | ||
| - easy to reason about in logs, APIs, and databases | ||
| This library provides a Python package with optional Rust acceleration. | ||
| ## Key features | ||
| - ✅ UUIDv7-based, time-sortable identifiers | ||
| - ✅ Type-safe prefixes (`user_`, `order_`, …) | ||
| - ✅ Human-readable and URL-safe | ||
| - ✅ Fast generation & parsing (Rust-accelerated) | ||
| - ✅ CLI tools (`new`, `encode`, `decode`, `explain`) | ||
| - ✅ Schema-based ID explanations (JSON / YAML) | ||
| - ✅ Fully offline, no external services | ||
| ## Performance | ||
| TypeID is optimized for **real-world performance**, not just correctness. | ||
| ### Benchmark summary (mean time) | ||
| | Operation | Before Rust | Rust + optimizations | | ||
| | --------- | ----------- | -------------------- | | ||
| | Generate | 3.47 µs | **0.70 µs** | | ||
| | Parse | 2.08 µs | **1.30 µs** | | ||
| | Workflow | 5.52 µs | **2.25 µs** | | ||
| ### Highlights | ||
| * 🚀 **~5× faster generation** | ||
| * ⚡ **~1.6× faster parsing** | ||
| * 🔁 **~2.5× faster end-to-end workflows** | ||
| Benchmarks are: | ||
| * reproducible | ||
| * committed as raw JSON | ||
| * runnable locally via `bench/` | ||
| See [`Docs: Performance`](https://akhundmurad.github.io/typeid-python/performance/) for details. | ||
| ## Installation | ||
| ### Core | ||
| ```console | ||
| $ pip install typeid-python | ||
| ``` | ||
| Included: | ||
| * Rust base32 encode/decode | ||
| * `uuid-utils` for fast UUIDv7 generation | ||
| ### Other optional extras | ||
| ```console | ||
| $ pip install typeid-python[yaml] # YAML schema support | ||
| $ pip install typeid-python[cli] # CLI tools | ||
| ``` | ||
| Extras are **strictly optional**. | ||
| ## Usage | ||
| ### Basic | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID(prefix="user") | ||
| assert tid.prefix == "user" | ||
| assert isinstance(tid.suffix, str) | ||
| assert str(tid).startswith("user_") | ||
| ``` | ||
| ### From string | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID.from_string("user_01h45ytscbebyvny4gc8cr8ma2") | ||
| assert tid.prefix == "user" | ||
| ``` | ||
| ### From UUIDv7 | ||
| ```python | ||
| from typeid import TypeID | ||
| from uuid_utils import uuid7 | ||
| u = uuid7() | ||
| tid = TypeID.from_uuid(prefix="user", suffix=u) | ||
| assert tid.uuid.version == 7 | ||
| ``` | ||
| ### Typed prefixes | ||
| ```python | ||
| from typing import Literal | ||
| from typeid import TypeID, typeid_factory | ||
| UserID = TypeID[Literal["user"]] | ||
| gen_user_id = typeid_factory("user") | ||
| user_id = gen_user_id() | ||
| ``` | ||
| ## CLI | ||
| ```console | ||
| $ pip install typeid-python[cli] | ||
| ``` | ||
| Generate: | ||
| ```console | ||
| $ typeid new -p user | ||
| user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| ``` | ||
| Decode: | ||
| ```console | ||
| $ typeid decode user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| uuid: 0188bac7-4afa-78aa-bc3b-bd1eef28d881 | ||
| ``` | ||
| Encode: | ||
| ```console | ||
| $ typeid encode 0188bac7-4afa-78aa-bc3b-bd1eef28d881 --prefix user | ||
| ``` | ||
| ## ✨ `typeid explain` — understand any ID | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Outputs: | ||
| ```yaml | ||
| parsed: | ||
| prefix: user | ||
| uuid: 01890bf0-846f-7762-8605-5a3abb40e0e5 | ||
| created_at: 2025-03-12T10:41:23Z | ||
| sortable: true | ||
| ``` | ||
| Works **without schema**, fully offline. | ||
| ## Schema-based explanations | ||
| Define meaning for prefixes using JSON or YAML. | ||
| Example (`typeid.schema.json`): | ||
| ```json | ||
| { | ||
| "schema_version": 1, | ||
| "types": { | ||
| "user": { | ||
| "name": "User", | ||
| "owner_team": "identity-platform", | ||
| "pii": true | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| Then: | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Read more here: ["Docs: Explain"](https://akhundmurad.github.io/typeid-python/performance/). | ||
| ## Design principles | ||
| * **Non-breaking**: stable APIs | ||
| * **Optional acceleration**: Rust is opt-in | ||
| * **Lazy evaluation**: work is done only when needed | ||
| * **Explainability**: identifiers carry meaning | ||
| * **Transparency**: performance claims are backed by data | ||
| > Think of TypeID as | ||
| > **UUIDs + semantics + observability — without sacrificing speed** | ||
| ## License | ||
| MIT | ||
| [project] | ||
| name = "typeid-python" | ||
| version = "0.3.7" | ||
| description = "Python implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs" | ||
| authors = [{ name = "Murad Akhundov", email = "akhundov1murad@gmail.com" }] | ||
| requires-python = ">=3.10,<4" | ||
| readme = "README.md" | ||
| license = { file = "LICENSE" } | ||
| keywords = ["typeid", "uuid", "rust", "guid", "uuid7"] | ||
| classifiers = [ | ||
| "Development Status :: 3 - Alpha", | ||
| "License :: OSI Approved :: MIT License", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Python :: 3.13", | ||
| "Programming Language :: Python :: 3.14", | ||
| "Operating System :: OS Independent", | ||
| ] | ||
| dependencies = ["uuid-utils>=0.12.0"] | ||
| [project.optional-dependencies] | ||
| cli = ["click"] | ||
| yaml = ["PyYAML"] | ||
| [project.urls] | ||
| Homepage = "https://github.com/akhundMurad/typeid-python" | ||
| Repository = "https://github.com/akhundMurad/typeid-python" | ||
| "Bug Tracker" = "https://github.com/akhundMurad/typeid-python/issues" | ||
| [project.scripts] | ||
| typeid = "typeid.cli:cli" | ||
| [dependency-groups] | ||
| dev = [ | ||
| "pytest>=7.3.2,<8", | ||
| "black>=23.3.0,<24", | ||
| "mypy>=1.3.0,<2", | ||
| "requests>=2.31.0,<3", | ||
| "ruff>=0.14.5,<0.15", | ||
| "twine>=6.2.0,<7", | ||
| "pyyaml>=6.0", | ||
| "mkdocs-material>=9.7.1", | ||
| "mkdocstrings[python]>=1.0.0", | ||
| "mkdocs-git-revision-date-localized-plugin>=1.5.0", | ||
| "mkdocs-gen-files>=0.6.0", | ||
| "mkdocs-literate-nav>=0.6.2", | ||
| "mkdocs-section-index>=0.3.10", | ||
| "pytest-markdown-docs>=0.9.0", | ||
| "pytest-benchmark>=5.0.1", | ||
| "maturin>=1.5; platform_system != 'Windows'", | ||
| ] | ||
| [build-system] | ||
| requires = ["maturin>=1.5"] | ||
| build-backend = "maturin" | ||
| [tool.maturin] | ||
| python-source = "." | ||
| manifest-path = "rust-base32/Cargo.toml" | ||
| module-name = "typeid._base32" | ||
| features = ["pyo3/extension-module"] | ||
| include = ["LICENSE", "README.md", "typeid/**", "rust-base32/**"] |
+210
| # TypeID Python | ||
| [](https://github.com/akhundMurad/typeid-python/actions/workflows/test.yml) | ||
| [](https://pepy.tech/projects/typeid-python) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| A **high-performance Python implementation of [TypeIDs](https://github.com/jetpack-io/typeid)** — type-safe, | ||
| sortable identifiers based on **UUIDv7**. | ||
| TypeIDs are designed for modern systems where identifiers should be: | ||
| - globally unique | ||
| - sortable by creation time | ||
| - safe to expose externally | ||
| - easy to reason about in logs, APIs, and databases | ||
| This library provides a Python package with optional Rust acceleration. | ||
| ## Key features | ||
| - ✅ UUIDv7-based, time-sortable identifiers | ||
| - ✅ Type-safe prefixes (`user_`, `order_`, …) | ||
| - ✅ Human-readable and URL-safe | ||
| - ✅ Fast generation & parsing (Rust-accelerated) | ||
| - ✅ CLI tools (`new`, `encode`, `decode`, `explain`) | ||
| - ✅ Schema-based ID explanations (JSON / YAML) | ||
| - ✅ Fully offline, no external services | ||
| ## Performance | ||
| TypeID is optimized for **real-world performance**, not just correctness. | ||
| ### Benchmark summary (mean time) | ||
| | Operation | Before Rust | Rust + optimizations | | ||
| | --------- | ----------- | -------------------- | | ||
| | Generate | 3.47 µs | **0.70 µs** | | ||
| | Parse | 2.08 µs | **1.30 µs** | | ||
| | Workflow | 5.52 µs | **2.25 µs** | | ||
| ### Highlights | ||
| * 🚀 **~5× faster generation** | ||
| * ⚡ **~1.6× faster parsing** | ||
| * 🔁 **~2.5× faster end-to-end workflows** | ||
| Benchmarks are: | ||
| * reproducible | ||
| * committed as raw JSON | ||
| * runnable locally via `bench/` | ||
| See [`Docs: Performance`](https://akhundmurad.github.io/typeid-python/performance/) for details. | ||
| ## Installation | ||
| ### Core | ||
| ```console | ||
| $ pip install typeid-python | ||
| ``` | ||
| Included: | ||
| * Rust base32 encode/decode | ||
| * `uuid-utils` for fast UUIDv7 generation | ||
| ### Other optional extras | ||
| ```console | ||
| $ pip install typeid-python[yaml] # YAML schema support | ||
| $ pip install typeid-python[cli] # CLI tools | ||
| ``` | ||
| Extras are **strictly optional**. | ||
| ## Usage | ||
| ### Basic | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID(prefix="user") | ||
| assert tid.prefix == "user" | ||
| assert isinstance(tid.suffix, str) | ||
| assert str(tid).startswith("user_") | ||
| ``` | ||
| ### From string | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID.from_string("user_01h45ytscbebyvny4gc8cr8ma2") | ||
| assert tid.prefix == "user" | ||
| ``` | ||
| ### From UUIDv7 | ||
| ```python | ||
| from typeid import TypeID | ||
| from uuid_utils import uuid7 | ||
| u = uuid7() | ||
| tid = TypeID.from_uuid(prefix="user", suffix=u) | ||
| assert tid.uuid.version == 7 | ||
| ``` | ||
| ### Typed prefixes | ||
| ```python | ||
| from typing import Literal | ||
| from typeid import TypeID, typeid_factory | ||
| UserID = TypeID[Literal["user"]] | ||
| gen_user_id = typeid_factory("user") | ||
| user_id = gen_user_id() | ||
| ``` | ||
| ## CLI | ||
| ```console | ||
| $ pip install typeid-python[cli] | ||
| ``` | ||
| Generate: | ||
| ```console | ||
| $ typeid new -p user | ||
| user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| ``` | ||
| Decode: | ||
| ```console | ||
| $ typeid decode user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| uuid: 0188bac7-4afa-78aa-bc3b-bd1eef28d881 | ||
| ``` | ||
| Encode: | ||
| ```console | ||
| $ typeid encode 0188bac7-4afa-78aa-bc3b-bd1eef28d881 --prefix user | ||
| ``` | ||
| ## ✨ `typeid explain` — understand any ID | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Outputs: | ||
| ```yaml | ||
| parsed: | ||
| prefix: user | ||
| uuid: 01890bf0-846f-7762-8605-5a3abb40e0e5 | ||
| created_at: 2025-03-12T10:41:23Z | ||
| sortable: true | ||
| ``` | ||
| Works **without schema**, fully offline. | ||
| ## Schema-based explanations | ||
| Define meaning for prefixes using JSON or YAML. | ||
| Example (`typeid.schema.json`): | ||
| ```json | ||
| { | ||
| "schema_version": 1, | ||
| "types": { | ||
| "user": { | ||
| "name": "User", | ||
| "owner_team": "identity-platform", | ||
| "pii": true | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| Then: | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Read more here: ["Docs: Explain"](https://akhundmurad.github.io/typeid-python/performance/). | ||
| ## Design principles | ||
| * **Non-breaking**: stable APIs | ||
| * **Optional acceleration**: Rust is opt-in | ||
| * **Lazy evaluation**: work is done only when needed | ||
| * **Explainability**: identifiers carry meaning | ||
| * **Transparency**: performance claims are backed by data | ||
| > Think of TypeID as | ||
| > **UUIDs + semantics + observability — without sacrificing speed** | ||
| ## License | ||
| MIT |
| # This file is automatically @generated by Cargo. | ||
| # It is not intended for manual editing. | ||
| version = 4 | ||
| [[package]] | ||
| name = "autocfg" | ||
| version = "1.5.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" | ||
| [[package]] | ||
| name = "heck" | ||
| version = "0.5.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | ||
| [[package]] | ||
| name = "indoc" | ||
| version = "2.0.7" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" | ||
| dependencies = [ | ||
| "rustversion", | ||
| ] | ||
| [[package]] | ||
| name = "libc" | ||
| version = "0.2.178" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" | ||
| [[package]] | ||
| name = "memoffset" | ||
| version = "0.9.1" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" | ||
| dependencies = [ | ||
| "autocfg", | ||
| ] | ||
| [[package]] | ||
| name = "once_cell" | ||
| version = "1.21.3" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" | ||
| [[package]] | ||
| name = "portable-atomic" | ||
| version = "1.13.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" | ||
| [[package]] | ||
| name = "proc-macro2" | ||
| version = "1.0.104" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" | ||
| dependencies = [ | ||
| "unicode-ident", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3" | ||
| version = "0.27.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d" | ||
| dependencies = [ | ||
| "indoc", | ||
| "libc", | ||
| "memoffset", | ||
| "once_cell", | ||
| "portable-atomic", | ||
| "pyo3-build-config", | ||
| "pyo3-ffi", | ||
| "pyo3-macros", | ||
| "unindent", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-build-config" | ||
| version = "0.27.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6" | ||
| dependencies = [ | ||
| "target-lexicon", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-ffi" | ||
| version = "0.27.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089" | ||
| dependencies = [ | ||
| "libc", | ||
| "pyo3-build-config", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-macros" | ||
| version = "0.27.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "pyo3-macros-backend", | ||
| "quote", | ||
| "syn", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-macros-backend" | ||
| version = "0.27.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9" | ||
| dependencies = [ | ||
| "heck", | ||
| "proc-macro2", | ||
| "pyo3-build-config", | ||
| "quote", | ||
| "syn", | ||
| ] | ||
| [[package]] | ||
| name = "quote" | ||
| version = "1.0.42" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| ] | ||
| [[package]] | ||
| name = "rustversion" | ||
| version = "1.0.22" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" | ||
| [[package]] | ||
| name = "syn" | ||
| version = "2.0.112" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "quote", | ||
| "unicode-ident", | ||
| ] | ||
| [[package]] | ||
| name = "target-lexicon" | ||
| version = "0.13.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba" | ||
| [[package]] | ||
| name = "typeid-base32" | ||
| version = "0.3.7" | ||
| dependencies = [ | ||
| "pyo3", | ||
| ] | ||
| [[package]] | ||
| name = "unicode-ident" | ||
| version = "1.0.22" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" | ||
| [[package]] | ||
| name = "unindent" | ||
| version = "0.2.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" |
| [package] | ||
| name = "typeid-base32" | ||
| version = "0.3.7" | ||
| edition = "2021" | ||
| description = "Rust-accelerated base32 codec for typeid-python" | ||
| license = "MIT" | ||
| repository = "https://github.com/akhundMurad/typeid-python" | ||
| [lib] | ||
| name = "_base32" | ||
| crate-type = ["cdylib"] | ||
| [dependencies] | ||
| pyo3 = { version = "0.27.2", features = ["extension-module"] } |
| use pyo3::exceptions::PyRuntimeError; | ||
| use pyo3::prelude::*; | ||
| use pyo3::types::PyModule; | ||
| const SUFFIX_LEN: usize = 26; | ||
| const UUID_LEN: usize = 16; | ||
| const ALPHABET: &[u8; 32] = b"0123456789abcdefghjkmnpqrstvwxyz"; | ||
| #[inline] | ||
| fn build_table() -> [u8; 256] { | ||
| let mut t = [0xFFu8; 256]; | ||
| for (i, &ch) in ALPHABET.iter().enumerate() { | ||
| t[ch as usize] = i as u8; | ||
| } | ||
| t | ||
| } | ||
| #[pyfunction] | ||
| fn encode(src: &[u8]) -> PyResult<String> { | ||
| if src.len() != UUID_LEN { | ||
| return Err(PyRuntimeError::new_err("Invalid length (expected 16 bytes).")); | ||
| } | ||
| let b = src; | ||
| let mut out = [0u8; SUFFIX_LEN]; | ||
| // Timestamp (6 bytes => 10 chars) | ||
| out[0] = ALPHABET[((b[0] & 0b1110_0000) >> 5) as usize]; | ||
| out[1] = ALPHABET[(b[0] & 0b0001_1111) as usize]; | ||
| out[2] = ALPHABET[((b[1] & 0b1111_1000) >> 3) as usize]; | ||
| out[3] = ALPHABET[(((b[1] & 0b0000_0111) << 2) | ((b[2] & 0b1100_0000) >> 6)) as usize]; | ||
| out[4] = ALPHABET[((b[2] & 0b0011_1110) >> 1) as usize]; | ||
| out[5] = ALPHABET[(((b[2] & 0b0000_0001) << 4) | ((b[3] & 0b1111_0000) >> 4)) as usize]; | ||
| out[6] = ALPHABET[(((b[3] & 0b0000_1111) << 1) | ((b[4] & 0b1000_0000) >> 7)) as usize]; | ||
| out[7] = ALPHABET[((b[4] & 0b0111_1100) >> 2) as usize]; | ||
| out[8] = ALPHABET[(((b[4] & 0b0000_0011) << 3) | ((b[5] & 0b1110_0000) >> 5)) as usize]; | ||
| out[9] = ALPHABET[(b[5] & 0b0001_1111) as usize]; | ||
| // Entropy (10 bytes => 16 chars) | ||
| out[10] = ALPHABET[((b[6] & 0b1111_1000) >> 3) as usize]; | ||
| out[11] = ALPHABET[(((b[6] & 0b0000_0111) << 2) | ((b[7] & 0b1100_0000) >> 6)) as usize]; | ||
| out[12] = ALPHABET[((b[7] & 0b0011_1110) >> 1) as usize]; | ||
| out[13] = ALPHABET[(((b[7] & 0b0000_0001) << 4) | ((b[8] & 0b1111_0000) >> 4)) as usize]; | ||
| out[14] = ALPHABET[(((b[8] & 0b0000_1111) << 1) | ((b[9] & 0b1000_0000) >> 7)) as usize]; | ||
| out[15] = ALPHABET[((b[9] & 0b0111_1100) >> 2) as usize]; | ||
| out[16] = ALPHABET[(((b[9] & 0b0000_0011) << 3) | ((b[10] & 0b1110_0000) >> 5)) as usize]; | ||
| out[17] = ALPHABET[(b[10] & 0b0001_1111) as usize]; | ||
| out[18] = ALPHABET[((b[11] & 0b1111_1000) >> 3) as usize]; | ||
| out[19] = ALPHABET[(((b[11] & 0b0000_0111) << 2) | ((b[12] & 0b1100_0000) >> 6)) as usize]; | ||
| out[20] = ALPHABET[((b[12] & 0b0011_1110) >> 1) as usize]; | ||
| out[21] = ALPHABET[(((b[12] & 0b0000_0001) << 4) | ((b[13] & 0b1111_0000) >> 4)) as usize]; | ||
| out[22] = ALPHABET[(((b[13] & 0b0000_1111) << 1) | ((b[14] & 0b1000_0000) >> 7)) as usize]; | ||
| out[23] = ALPHABET[((b[14] & 0b0111_1100) >> 2) as usize]; | ||
| out[24] = ALPHABET[(((b[14] & 0b0000_0011) << 3) | ((b[15] & 0b1110_0000) >> 5)) as usize]; | ||
| out[25] = ALPHABET[(b[15] & 0b0001_1111) as usize]; | ||
| // Safe because alphabet is ASCII | ||
| Ok(String::from_utf8(out.to_vec()).unwrap()) | ||
| } | ||
| #[pyfunction] | ||
| fn decode(s: &str) -> PyResult<Vec<u8>> { | ||
| if s.len() != SUFFIX_LEN { | ||
| return Err(PyRuntimeError::new_err("Invalid length (expected 26 chars).")); | ||
| } | ||
| let t = build_table(); | ||
| let bytes = s.as_bytes(); | ||
| // Validate | ||
| for &ch in bytes { | ||
| if t[ch as usize] == 0xFF { | ||
| return Err(PyRuntimeError::new_err("Invalid base32 character.")); | ||
| } | ||
| } | ||
| #[inline] | ||
| fn v(t: &[u8; 256], bytes: &[u8], i: usize) -> u8 { | ||
| t[bytes[i] as usize] | ||
| } | ||
| let mut out = [0u8; UUID_LEN]; | ||
| // Timestamp (48 bits) | ||
| out[0] = (v(&t, bytes, 0) << 5) | v(&t, bytes, 1); | ||
| out[1] = (v(&t, bytes, 2) << 3) | (v(&t, bytes, 3) >> 2); | ||
| out[2] = ((v(&t, bytes, 3) & 3) << 6) | (v(&t, bytes, 4) << 1) | (v(&t, bytes, 5) >> 4); | ||
| out[3] = ((v(&t, bytes, 5) & 15) << 4) | (v(&t, bytes, 6) >> 1); | ||
| out[4] = ((v(&t, bytes, 6) & 1) << 7) | (v(&t, bytes, 7) << 2) | (v(&t, bytes, 8) >> 3); | ||
| out[5] = ((v(&t, bytes, 8) & 7) << 5) | v(&t, bytes, 9); | ||
| // Entropy (80 bits) | ||
| out[6] = (v(&t, bytes, 10) << 3) | (v(&t, bytes, 11) >> 2); | ||
| out[7] = ((v(&t, bytes, 11) & 3) << 6) | (v(&t, bytes, 12) << 1) | (v(&t, bytes, 13) >> 4); | ||
| out[8] = ((v(&t, bytes, 13) & 15) << 4) | (v(&t, bytes, 14) >> 1); | ||
| out[9] = ((v(&t, bytes, 14) & 1) << 7) | (v(&t, bytes, 15) << 2) | (v(&t, bytes, 16) >> 3); | ||
| out[10] = ((v(&t, bytes, 16) & 7) << 5) | v(&t, bytes, 17); | ||
| out[11] = (v(&t, bytes, 18) << 3) | (v(&t, bytes, 19) >> 2); | ||
| out[12] = ((v(&t, bytes, 19) & 3) << 6) | (v(&t, bytes, 20) << 1) | (v(&t, bytes, 21) >> 4); | ||
| out[13] = ((v(&t, bytes, 21) & 15) << 4) | (v(&t, bytes, 22) >> 1); | ||
| out[14] = ((v(&t, bytes, 22) & 1) << 7) | (v(&t, bytes, 23) << 2) | (v(&t, bytes, 24) >> 3); | ||
| out[15] = ((v(&t, bytes, 24) & 7) << 5) | v(&t, bytes, 25); | ||
| Ok(out.to_vec()) | ||
| } | ||
| #[pymodule] | ||
| fn _base32(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { | ||
| m.add_function(wrap_pyfunction!(encode, m)?)?; | ||
| m.add_function(wrap_pyfunction!(decode, m)?)?; | ||
| Ok(()) | ||
| } |
| [console_scripts] | ||
| typeid=typeid.cli:cli |
| MIT License | ||
| Copyright (c) 2023 Murad Akhundov | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
-238
| Metadata-Version: 2.4 | ||
| Name: typeid-python | ||
| Version: 0.3.6 | ||
| Classifier: Development Status :: 3 - Alpha | ||
| Classifier: License :: OSI Approved :: MIT License | ||
| Classifier: Programming Language :: Python :: 3.10 | ||
| Classifier: Programming Language :: Python :: 3.11 | ||
| Classifier: Programming Language :: Python :: 3.12 | ||
| Classifier: Programming Language :: Python :: 3.13 | ||
| Classifier: Programming Language :: Python :: 3.14 | ||
| Classifier: Operating System :: OS Independent | ||
| Requires-Dist: uuid-utils>=0.12.0 | ||
| Requires-Dist: click ; extra == 'cli' | ||
| Requires-Dist: pyyaml ; extra == 'yaml' | ||
| Provides-Extra: cli | ||
| Provides-Extra: yaml | ||
| License-File: LICENSE | ||
| Summary: Python implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs | ||
| Keywords: typeid,uuid,rust,guid,uuid7 | ||
| Author-email: Murad Akhundov <akhundov1murad@gmail.com> | ||
| License-Expression: MIT | ||
| Requires-Python: >=3.10, <4 | ||
| Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM | ||
| Project-URL: Homepage, https://github.com/akhundMurad/typeid-python | ||
| Project-URL: Repository, https://github.com/akhundMurad/typeid-python | ||
| Project-URL: Bug Tracker, https://github.com/akhundMurad/typeid-python/issues | ||
| # TypeID Python | ||
| [](https://github.com/akhundMurad/typeid-python/actions/workflows/test.yml) | ||
| [](https://pepy.tech/projects/typeid-python) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| [](https://pypi.org/project/typeid-python/) | ||
| A **high-performance Python implementation of [TypeIDs](https://github.com/jetpack-io/typeid)** — type-safe, | ||
| sortable identifiers based on **UUIDv7**. | ||
| TypeIDs are designed for modern systems where identifiers should be: | ||
| - globally unique | ||
| - sortable by creation time | ||
| - safe to expose externally | ||
| - easy to reason about in logs, APIs, and databases | ||
| This library provides a Python package with optional Rust acceleration. | ||
| ## Key features | ||
| - ✅ UUIDv7-based, time-sortable identifiers | ||
| - ✅ Type-safe prefixes (`user_`, `order_`, …) | ||
| - ✅ Human-readable and URL-safe | ||
| - ✅ Fast generation & parsing (Rust-accelerated) | ||
| - ✅ CLI tools (`new`, `encode`, `decode`, `explain`) | ||
| - ✅ Schema-based ID explanations (JSON / YAML) | ||
| - ✅ Fully offline, no external services | ||
| ## Performance | ||
| TypeID is optimized for **real-world performance**, not just correctness. | ||
| ### Benchmark summary (mean time) | ||
| | Operation | Before Rust | Rust + optimizations | | ||
| | --------- | ----------- | -------------------- | | ||
| | Generate | 3.47 µs | **0.70 µs** | | ||
| | Parse | 2.08 µs | **1.30 µs** | | ||
| | Workflow | 5.52 µs | **2.25 µs** | | ||
| ### Highlights | ||
| * 🚀 **~5× faster generation** | ||
| * ⚡ **~1.6× faster parsing** | ||
| * 🔁 **~2.5× faster end-to-end workflows** | ||
| Benchmarks are: | ||
| * reproducible | ||
| * committed as raw JSON | ||
| * runnable locally via `bench/` | ||
| See [`Docs: Performance`](https://akhundmurad.github.io/typeid-python/performance/) for details. | ||
| ## Installation | ||
| ### Core | ||
| ```console | ||
| $ pip install typeid-python | ||
| ``` | ||
| Included: | ||
| * Rust base32 encode/decode | ||
| * `uuid-utils` for fast UUIDv7 generation | ||
| ### Other optional extras | ||
| ```console | ||
| $ pip install typeid-python[yaml] # YAML schema support | ||
| $ pip install typeid-python[cli] # CLI tools | ||
| ``` | ||
| Extras are **strictly optional**. | ||
| ## Usage | ||
| ### Basic | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID(prefix="user") | ||
| assert tid.prefix == "user" | ||
| assert isinstance(tid.suffix, str) | ||
| assert str(tid).startswith("user_") | ||
| ``` | ||
| ### From string | ||
| ```python | ||
| from typeid import TypeID | ||
| tid = TypeID.from_string("user_01h45ytscbebyvny4gc8cr8ma2") | ||
| assert tid.prefix == "user" | ||
| ``` | ||
| ### From UUIDv7 | ||
| ```python | ||
| from typeid import TypeID | ||
| from uuid_utils import uuid7 | ||
| u = uuid7() | ||
| tid = TypeID.from_uuid(prefix="user", suffix=u) | ||
| assert tid.uuid.version == 7 | ||
| ``` | ||
| ### Typed prefixes | ||
| ```python | ||
| from typing import Literal | ||
| from typeid import TypeID, typeid_factory | ||
| UserID = TypeID[Literal["user"]] | ||
| gen_user_id = typeid_factory("user") | ||
| user_id = gen_user_id() | ||
| ``` | ||
| ## CLI | ||
| ```console | ||
| $ pip install typeid-python[cli] | ||
| ``` | ||
| Generate: | ||
| ```console | ||
| $ typeid new -p user | ||
| user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| ``` | ||
| Decode: | ||
| ```console | ||
| $ typeid decode user_01h2xcejqtf2nbrexx3vqjhp41 | ||
| uuid: 0188bac7-4afa-78aa-bc3b-bd1eef28d881 | ||
| ``` | ||
| Encode: | ||
| ```console | ||
| $ typeid encode 0188bac7-4afa-78aa-bc3b-bd1eef28d881 --prefix user | ||
| ``` | ||
| ## ✨ `typeid explain` — understand any ID | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Outputs: | ||
| ```yaml | ||
| parsed: | ||
| prefix: user | ||
| uuid: 01890bf0-846f-7762-8605-5a3abb40e0e5 | ||
| created_at: 2025-03-12T10:41:23Z | ||
| sortable: true | ||
| ``` | ||
| Works **without schema**, fully offline. | ||
| ## Schema-based explanations | ||
| Define meaning for prefixes using JSON or YAML. | ||
| Example (`typeid.schema.json`): | ||
| ```json | ||
| { | ||
| "schema_version": 1, | ||
| "types": { | ||
| "user": { | ||
| "name": "User", | ||
| "owner_team": "identity-platform", | ||
| "pii": true | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| Then: | ||
| ```console | ||
| $ typeid explain user_01h45ytscbebyvny4gc8cr8ma2 | ||
| ``` | ||
| Read more here: ["Docs: Explain"](https://akhundmurad.github.io/typeid-python/performance/). | ||
| ## Design principles | ||
| * **Non-breaking**: stable APIs | ||
| * **Optional acceleration**: Rust is opt-in | ||
| * **Lazy evaluation**: work is done only when needed | ||
| * **Explainability**: identifiers carry meaning | ||
| * **Transparency**: performance claims are backed by data | ||
| > Think of TypeID as | ||
| > **UUIDs + semantics + observability — without sacrificing speed** | ||
| ## License | ||
| MIT | ||
-21
| typeid/__init__.py,sha256=YWaZ6tmmlnlFfNQO2NmrzlEW04yRCp54H8A-pRTdH1E,314 | ||
| typeid/_base32.cpython-310-darwin.so,sha256=g-NS8BbilCnFDhHQie8IQQGhy-hf68XIXDoRXCnyEbY,487872 | ||
| typeid/base32.py,sha256=74oJ1Xm3wHTBY1DqaIk53tVxmL3V6yTnFDuOK4mkbhM,210 | ||
| typeid/cli.py,sha256=luCyGYbt0z1VhiCWcLVWaBspdOH8hWCHT0Kn1oznPk4,4159 | ||
| typeid/constants.py,sha256=ua-JigETdE4pZvOB9ALK_71sDOZKzOYIabHlJQ01yAw,84 | ||
| typeid/errors.py,sha256=2bSRH97Uvq_V1KnLadTmTNHAV5yOXOAHetJwz0YKDzc,225 | ||
| typeid/explain/__init__.py,sha256=2kSFzI_l7F9cXUAN_JTJbu-1ID-TlgLYJBl9hjkRz-A,2141 | ||
| typeid/explain/discovery.py,sha256=RKxebqLUqwQpHQp_nTO5PkK2-z8dejGHWtuw35VmAK8,3681 | ||
| typeid/explain/engine.py,sha256=-cKThbazfdvSNb1YvJ8JZ0t3N9Z2av0ubwMEsW0y_Os,8023 | ||
| typeid/explain/formatters.py,sha256=VAZGNGVKq52YS6ZjWPB28IGr_opiP676RSel95qV3iQ,6819 | ||
| typeid/explain/model.py,sha256=pd-vqA6SAAnPV1l5_ZVbTqwXoRLELd0n_7tbNtg17L8,5086 | ||
| typeid/explain/registry.py,sha256=DUQ6Jmk4M5la7Ye5BMXQMhqmDKjM36ohTUYx6ZRvjDo,6786 | ||
| typeid/factory.py,sha256=UJzWN8djufyYQhR08GmXyGrKfWaGIUvPv1GIKKG5RJo,909 | ||
| typeid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| typeid/typeid.py,sha256=axWR9dSXJ0QHZclPFHshe-vS1OjWANPBXbFEpAcT-ro,10657 | ||
| typeid/validation.py,sha256=0c2XWTkHro1gLaJmQnqW6XoSD1weSxWpBtEAbU157PI,1313 | ||
| typeid_python-0.3.6.dist-info/METADATA,sha256=9PVkYLwbrT_jpKp-dodrsbD6ZnkqvP00T8YM4bC3m2g,5810 | ||
| typeid_python-0.3.6.dist-info/WHEEL,sha256=IiUSfnZcnKtfg3tUHJ05sdhsIxnb0hSO-4fdRXTiMXo,105 | ||
| typeid_python-0.3.6.dist-info/entry_points.txt,sha256=nnZGQ4ygTxWYd3Wq1MknTNFLN76MIxJ8FFRB54QVhGs,40 | ||
| typeid_python-0.3.6.dist-info/licenses/LICENSE,sha256=f98oZ9FId4i3835UJYGw066BU8PSc57L1utGWS1ypcs,1070 | ||
| typeid_python-0.3.6.dist-info/RECORD,, |
Sorry, the diff of this file is not supported yet
-4
| Wheel-Version: 1.0 | ||
| Generator: maturin (1.10.2) | ||
| Root-Is-Purelib: false | ||
| Tag: cp310-cp310-macosx_11_0_arm64 |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
73400
Infinity%22
Infinity%1329
Infinity%