generated from rochacbruno/python-project-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extend built-in UUID class for uuid6, uuid7
- Loading branch information
1 parent
c9fa6a5
commit cc377a1
Showing
8 changed files
with
144 additions
and
82 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,27 @@ | ||
from uuid_v7.base import NAME | ||
from uuid_v7.base import uuid6, uuid7, UUID | ||
|
||
|
||
def test_base(): | ||
assert NAME == "uuid_v7" | ||
def test_uuid7_returns_uuid_instance(): | ||
assert isinstance(uuid7(), UUID) | ||
|
||
|
||
def test_uuid7_returns_unique_values(): | ||
for _ in range(1000): | ||
assert uuid7() != uuid7() | ||
|
||
|
||
def test_uuid7_correct_length(): | ||
assert len(str(uuid7())) == 36 | ||
|
||
|
||
def test_uuid6_returns_uuid_instance(): | ||
assert isinstance(uuid6(), UUID) | ||
|
||
|
||
def test_uuid6_returns_unique_values(): | ||
for _ in range(1000): | ||
assert uuid6() != uuid6() | ||
|
||
|
||
def test_uuid6_correct_length(): | ||
assert len(str(uuid6())) == 36 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.1.0 | ||
1.0.0 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,95 @@ | ||
""" | ||
uuid_v7 base module. | ||
from uuid import UUID as BaseUUID | ||
from uuid import SafeUUID | ||
|
||
This is the principal module of the uuid_v7 project. | ||
here you put your main classes and objects. | ||
|
||
Be creative! do whatever you want! | ||
class UUID(BaseUUID): | ||
def __init__( | ||
self, | ||
hex: str | None = None, | ||
bytes: bytes | None = None, | ||
bytes_le: bytes | None = None, | ||
fields: tuple[int, int, int, int, int, int] | None = None, | ||
int: int | None = None, | ||
version: int | None = None, | ||
*, | ||
is_safe: SafeUUID = SafeUUID.unknown | ||
) -> None: | ||
super().__init__( | ||
hex, bytes, bytes_le, fields, int, version=None, is_safe=is_safe | ||
) | ||
|
||
If you want to replace this with a Flask application run: | ||
if version is not None: | ||
if not 1 <= version <= 7: | ||
raise ValueError("illegal version number") | ||
# Set the variant to RFC 4122. | ||
int = int or 0 | ||
int &= ~(0xC000 << 48) | ||
int |= 0x8000 << 48 | ||
# Set the version number. | ||
int &= ~(0xF000 << 64) | ||
int |= version << 76 | ||
object.__setattr__(self, "int", int) | ||
object.__setattr__(self, "is_safe", is_safe) | ||
|
||
$ make init | ||
|
||
and then choose `flask` as template. | ||
""" | ||
_last_v6_timestamp = None | ||
_last_v7_timestamp = None | ||
|
||
# example constant variable | ||
NAME = "uuid_v7" | ||
|
||
def uuid6(clock_seq=None): | ||
"""Generate a UUID from sequence number, and the current time. | ||
If 'clock_seq' is given, it is used as the sequence number; | ||
otherwise a random 14-bit sequence number is chosen.""" | ||
|
||
global _last_v6_timestamp | ||
import random | ||
import time | ||
|
||
nanoseconds = time.time_ns() | ||
# 0x01b21dd213814000 is the number of 100-ns intervals between the | ||
# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. | ||
timestamp = nanoseconds // 100 + 0x01B21DD213814000 | ||
if _last_v6_timestamp is not None and timestamp <= _last_v6_timestamp: | ||
timestamp = _last_v6_timestamp + 1 | ||
_last_v6_timestamp = timestamp | ||
if clock_seq is None: | ||
clock_seq = random.SystemRandom().getrandbits( | ||
14 | ||
) # instead of stable storage | ||
node = random.SystemRandom().getrandbits(48) | ||
time_high_and_time_mid = (timestamp >> 12) & 0xFFFFFFFFFFFF | ||
time_low_and_version = timestamp & 0x0FFF | ||
uuid_int = time_high_and_time_mid << 80 | ||
uuid_int += time_low_and_version << 64 | ||
uuid_int += (clock_seq & 0x3FFF) << 48 | ||
uuid_int += node | ||
return UUID(int=uuid_int, version=6) | ||
|
||
|
||
def uuid7(): | ||
"""The UUIDv7 format is designed to encode a Unix timestamp with | ||
arbitrary sub-second precision. The key property provided by UUIDv7 | ||
is that timestamp values generated by one system and parsed by | ||
another are guaranteed to have sub-second precision of either the | ||
generator or the parser, whichever is less. Additionally, the system | ||
parsing the UUIDv7 value does not need to know which precision was | ||
used during encoding in order to function correctly.""" | ||
|
||
global _last_v7_timestamp | ||
import random | ||
import time | ||
|
||
nanoseconds = time.time_ns() | ||
if _last_v7_timestamp is not None and nanoseconds <= _last_v7_timestamp: | ||
nanoseconds = _last_v7_timestamp + 1 | ||
_last_v7_timestamp = nanoseconds | ||
timestamp_s, timestamp_ns = divmod(nanoseconds, 10**9) | ||
subsec_a = timestamp_ns >> 18 | ||
subsec_b = (timestamp_ns >> 6) & 0x0FFF | ||
subsec_seq_node = (timestamp_ns & 0x3F) << 56 | ||
subsec_seq_node += random.SystemRandom().getrandbits(56) | ||
uuid_int = (timestamp_s & 0x0FFFFFFFFF) << 92 | ||
uuid_int += subsec_a << 80 | ||
uuid_int += subsec_b << 64 | ||
uuid_int += subsec_seq_node | ||
return UUID(int=uuid_int, version=7) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,2 @@ | ||
"""CLI interface for uuid_v7 project. | ||
Be creative! do whatever you want! | ||
- Install click or typer and create a CLI app | ||
- Use builtin argparse | ||
- Start a web application | ||
- Import things from your .base module | ||
""" | ||
|
||
|
||
def main(): # pragma: no cover | ||
""" | ||
The main function executes on commands: | ||
`python -m uuid_v7` and `$ uuid_v7 `. | ||
This is your program's entry point. | ||
You can change this function to do whatever you want. | ||
Examples: | ||
* Run a test suite | ||
* Run a server | ||
* Do some other stuff | ||
* Run a command line application (Click, Typer, ArgParse) | ||
* List all available tasks | ||
* Run an application (Flask, FastAPI, Django, etc.) | ||
""" | ||
print("This will do something") | ||
def main(): | ||
pass |