From c5b5cfbc138c0acbc450edf2e2f8d72c7aa0d77f Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:08:50 +0200 Subject: [PATCH 1/4] Add test for uuidv7 generation. --- pyleco/core/serialization.py | 11 +++++++++-- tests/core/test_serialization.py | 12 ++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pyleco/core/serialization.py b/pyleco/core/serialization.py index db043ecb..745566f8 100644 --- a/pyleco/core/serialization.py +++ b/pyleco/core/serialization.py @@ -23,11 +23,13 @@ # from __future__ import annotations +import datetime from enum import IntEnum, IntFlag import json -from typing import Any, Optional, NamedTuple, Union +from typing import Any, cast, Optional, NamedTuple, Union -from uuid_extensions import uuid7 # type: ignore # as long as uuid does not yet support UUIDv7 +# as long as uuid does not yet support UUIDv7 use uuid_extensions +from uuid_extensions import uuid7, uuid_to_datetime # type: ignore from ..json_utils.json_objects import ( Request, ParamsRequest, @@ -155,6 +157,11 @@ def generate_conversation_id() -> bytes: return uuid7(as_type="bytes") # type: ignore +def conversation_id_to_datetime(conversation_id: bytes) -> datetime.datetime: + return cast(datetime.datetime, uuid_to_datetime(conversation_id.decode(), + suppress_error=False)) + + def _get_json_object_type(data: dict[str, Any]) -> JsonContentTypes: if isinstance(data, dict): if "method" in data.keys(): diff --git a/tests/core/test_serialization.py b/tests/core/test_serialization.py index bb950841..b99f03ae 100644 --- a/tests/core/test_serialization.py +++ b/tests/core/test_serialization.py @@ -23,6 +23,7 @@ # from __future__ import annotations +import datetime from typing import Any, Optional, Union import pytest @@ -108,6 +109,17 @@ def test_UUID_version(self, conversation_id): def test_variant(self, conversation_id): assert conversation_id[8] >> 6 == 0b10 + def test_valid_UUIDv7(self): + """According to the draft https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122bis/14/ + 017F22E2-79B0-7CC3-98C4-DC0C0C07398F should be a timestamp of February 22, 2022, 2:22:22.00 + GMT-5 + """ + assert serialization.conversation_id_to_datetime( + b"017F22E2-79B0-7CC3-98C4-DC0C0C07398F" + ) == datetime.datetime( + 2022, 2, 22, 2, 22, 22, tzinfo=datetime.timezone(datetime.timedelta(-5)) + ) + def test_json_type_result_is_response(): assert JsonContentTypes.RESPONSE in JsonContentTypes.RESULT_RESPONSE From 6eb2f31cf494247d8401bbc843c05e0dddf442c9 Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Sat, 4 May 2024 12:17:48 +0200 Subject: [PATCH 2/4] Fix tests and conversation_id_to_datetime --- pyleco/core/serialization.py | 4 ++-- tests/core/test_serialization.py | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/pyleco/core/serialization.py b/pyleco/core/serialization.py index 745566f8..5dbcf1de 100644 --- a/pyleco/core/serialization.py +++ b/pyleco/core/serialization.py @@ -158,8 +158,8 @@ def generate_conversation_id() -> bytes: def conversation_id_to_datetime(conversation_id: bytes) -> datetime.datetime: - return cast(datetime.datetime, uuid_to_datetime(conversation_id.decode(), - suppress_error=False)) + seconds_since_epoch = int.from_bytes(conversation_id[:6], byteorder="big", signed=False) / 1000 + return datetime.datetime.fromtimestamp(seconds_since_epoch, tz=datetime.timezone.utc) def _get_json_object_type(data: dict[str, Any]) -> JsonContentTypes: diff --git a/tests/core/test_serialization.py b/tests/core/test_serialization.py index b99f03ae..5682e1b3 100644 --- a/tests/core/test_serialization.py +++ b/tests/core/test_serialization.py @@ -24,6 +24,7 @@ from __future__ import annotations import datetime +import uuid from typing import Any, Optional, Union import pytest @@ -109,16 +110,22 @@ def test_UUID_version(self, conversation_id): def test_variant(self, conversation_id): assert conversation_id[8] >> 6 == 0b10 - def test_valid_UUIDv7(self): - """According to the draft https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122bis/14/ - 017F22E2-79B0-7CC3-98C4-DC0C0C07398F should be a timestamp of February 22, 2022, 2:22:22.00 - GMT-5 - """ - assert serialization.conversation_id_to_datetime( - b"017F22E2-79B0-7CC3-98C4-DC0C0C07398F" - ) == datetime.datetime( - 2022, 2, 22, 2, 22, 22, tzinfo=datetime.timezone(datetime.timedelta(-5)) - ) + def test_correct_timestamp(self, conversation_id): + ts = serialization.conversation_id_to_datetime(conversation_id=conversation_id) + assert abs(ts - datetime.datetime.now(datetime.timezone.utc)) < datetime.timedelta(hours=1) + + +def test_conversation_id_to_datetime_according_to_uuid_example(): + """According to the draft https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122bis/14/ + 017F22E2-79B0-7CC3-98C4-DC0C0C07398F should be a timestamp of + Tuesday, February 22, 2022 2:22:22.00 PM GMT-05:00, represented as 1645557742000 + """ + cid = uuid.UUID("017F22E2-79B0-7CC3-98C4-DC0C0C07398F").bytes + reference = datetime.datetime( + 2022, 2, 22, 14, 22, 22, tzinfo=datetime.timezone(datetime.timedelta(hours=-5)) + ) + ts = serialization.conversation_id_to_datetime(cid) + assert reference - ts == datetime.timedelta(0) def test_json_type_result_is_response(): From 87421e11343a6de568f8dd079d60752bccd6c1c2 Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Sat, 4 May 2024 12:19:21 +0200 Subject: [PATCH 3/4] Switch from uuid7 package to uuid6 package. --- environment.yml | 2 +- pyleco/core/serialization.py | 8 ++++---- pyproject.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/environment.yml b/environment.yml index ee8a6724..86128c82 100644 --- a/environment.yml +++ b/environment.yml @@ -3,10 +3,10 @@ channels: - conda-forge dependencies: - pyzmq #=25.1.2 don't pin version for python<3.9 + - uuid6=2024.1.12 - pip # don't pin, to gain newest conda compatibility fixes - pip: # - openrpc==8.1.0 don't pin presence for python<3.9 - - uuid7==0.1.0 # Development dependencies below - pytest=7.2.0 - pytest-cov=4.1.0 diff --git a/pyleco/core/serialization.py b/pyleco/core/serialization.py index 5dbcf1de..94fc86f7 100644 --- a/pyleco/core/serialization.py +++ b/pyleco/core/serialization.py @@ -26,10 +26,10 @@ import datetime from enum import IntEnum, IntFlag import json -from typing import Any, cast, Optional, NamedTuple, Union +from typing import Any, Optional, NamedTuple, Union -# as long as uuid does not yet support UUIDv7 use uuid_extensions -from uuid_extensions import uuid7, uuid_to_datetime # type: ignore +# as long as uuid does not yet support UUIDv7 use uuid6 +from uuid6 import uuid7 from ..json_utils.json_objects import ( Request, ParamsRequest, @@ -154,7 +154,7 @@ def deserialize_data(content: bytes) -> Any: def generate_conversation_id() -> bytes: """Generate a conversation_id.""" - return uuid7(as_type="bytes") # type: ignore + return uuid7().bytes def conversation_id_to_datetime(conversation_id: bytes) -> datetime.datetime: diff --git a/pyproject.toml b/pyproject.toml index 531c47a4..c185948f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ requires-python = ">=3.8" dependencies = [ "pyzmq >= 22.3.0", "openrpc >= 8.1.0; python_version >= '3.9'", - "uuid7 >= 0.1.0", + "uuid6 >= 2024.1.12", ] [project.optional-dependencies] From b2a3b74f55bc5058f5c78e7aba6d8e37b950e29a Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Sat, 4 May 2024 12:22:38 +0200 Subject: [PATCH 4/4] Fix environment. --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index 86128c82..dd786f89 100644 --- a/environment.yml +++ b/environment.yml @@ -5,7 +5,7 @@ dependencies: - pyzmq #=25.1.2 don't pin version for python<3.9 - uuid6=2024.1.12 - pip # don't pin, to gain newest conda compatibility fixes - - pip: + # - pip: # - openrpc==8.1.0 don't pin presence for python<3.9 # Development dependencies below - pytest=7.2.0