Created
April 30, 2026 15:55
-
-
Save cellofellow/48b611499729d6662a828f674b5eb51c to your computer and use it in GitHub Desktop.
Tagged UUID types for Learner Provisioning Operator — type-safe, prefixed, runtime-enforced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Tagged UUID types for the Learner Provisioning Operator. | |
| Provides type-safe, prefixed UUIDs that: | |
| - Are distinguishable by type at both static analysis and runtime | |
| - Cannot compare equal across different ID types | |
| - Hash differently even if the underlying UUID bytes are identical | |
| - Serialize to "prefix-uuid" string format (e.g., "lrn-01961f3e-...") | |
| - Use a pluggable generator per subclass (default: uuidv7 for time-sortability) | |
| """ | |
| import uuid | |
| from typing import ClassVar, Callable, Self | |
| class TaggedId(uuid.UUID): | |
| prefix: ClassVar[str] | |
| generator: ClassVar[Callable[[], uuid.UUID]] = uuid.uuid4 | |
| def __init_subclass__( | |
| cls, | |
| prefix: str, | |
| generator: Callable[[], uuid.UUID] | None = None, | |
| **kwargs, | |
| ): | |
| super().__init_subclass__(**kwargs) | |
| cls.prefix = prefix | |
| if generator is not None: | |
| cls.generator = generator | |
| def __eq__(self, other: object) -> bool: | |
| if type(self) is not type(other): | |
| return NotImplemented | |
| return super().__eq__(other) | |
| def __ne__(self, other: object) -> bool: | |
| if type(self) is not type(other): | |
| return NotImplemented | |
| return super().__ne__(other) | |
| def __hash__(self) -> int: | |
| return hash((type(self), self.int)) | |
| def __str__(self) -> str: | |
| return f"{self.prefix}-{super().__str__()}" | |
| def __repr__(self) -> str: | |
| return f"{type(self).__name__}('{self}')" | |
| @classmethod | |
| def parse(cls, value: str) -> Self: | |
| if not value.startswith(f"{cls.prefix}-"): | |
| raise ValueError(f"Expected {cls.prefix}-prefixed ID, got: {value}") | |
| return cls(value.removeprefix(f"{cls.prefix}-")) | |
| @classmethod | |
| def generate(cls) -> Self: | |
| return cls(cls.generator().bytes) | |
| class LearnerId(TaggedId, prefix="lrn", generator=uuid.uuid7): ... | |
| class EnrollmentId(TaggedId, prefix="enr", generator=uuid.uuid7): ... | |
| if __name__ == "__main__": | |
| # Demo | |
| lid = LearnerId.generate() | |
| eid = EnrollmentId.generate() | |
| print(f"Learner ID: {lid}") | |
| print(f"Enrollment ID: {eid}") | |
| print(f"repr: {lid!r}") | |
| print(f"Parse: {LearnerId.parse(str(lid))}") | |
| print(f"Equal same: {lid == LearnerId(lid.bytes)}") | |
| print(f"Equal cross: {lid == EnrollmentId(lid.bytes)}") # False | |
| print(f"In set: {len({lid, EnrollmentId(lid.bytes)})}") # 2, not 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment