Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hatch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pre-install-commands = [

[envs.default.scripts]
sync = "pip install -r requirements-testing.txt"
test = "pytest --cov-config pyproject.toml {args:test}"
test = "pytest --cov-config pyproject.toml {args:test} -vv"
typing = "mypy {args:src test}"
style = [
"ruff check {args:.}",
Expand Down
2 changes: 1 addition & 1 deletion requirements-testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ pytest-timeout == 2.3.*
pytest-xdist == 3.6.*
black == 25.*
ruff == 0.11.*
mypy == 1.11.*
mypy == 1.15.*
psutil == 7.0.*
types-PyYAML ~= 6.0
17 changes: 8 additions & 9 deletions src/openjd/adaptor_runtime/_background/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import dataclasses as dataclasses
import json as json
from enum import Enum as Enum
from typing import Any, ClassVar, Dict, Generic, Iterable, Type, TypeVar, cast
from enum import EnumMeta
from typing import Any, ClassVar, Dict, Type, TypeVar, cast, Generic

from ..adaptors import AdaptorState

Expand Down Expand Up @@ -100,14 +101,12 @@ def map(self, o: Dict) -> _T:

value = o[field.name]
if dataclasses.is_dataclass(field.type):
value = DataclassMapper(field.type).map(value)
elif issubclass(field.type, Enum):
[value] = [
enum
# Need to cast here for mypy
for enum in cast(Iterable[Enum], list(field.type))
if enum.value == value
]
# The init function expects a type, so any dataclasses in cls
# will be a type.
value = DataclassMapper(cast(type, field.type)).map(value)
elif isinstance(field.type, EnumMeta):
value = field.type(value)

args[field.name] = value

return self._cls(**args)
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@

_ConfigType = TypeVar("_ConfigType", bound=Configuration)
_AdaptorConfigType = TypeVar("_AdaptorConfigType", bound=AdaptorConfiguration)
_AdaptorConfigClassType = Type[_AdaptorConfigType]


def create_adaptor_configuration_manager(
config_cls: Type[_AdaptorConfigType],
config_cls: _AdaptorConfigClassType,
adaptor_name: str,
default_config_path: str,
schema_path: str | List[str] | None = None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def terminate(self, grace_time_s: float = 60) -> None:
self._process.kill()
self._process.wait()
else:
signal_type: signal.Signals
if OSName.is_windows(): # pragma: is-posix
# We use `CREATE_NEW_PROCESS_GROUP` to create the process,
# so pid here is also the process group id and SIGBREAK can be only sent to the process group.
Expand Down
36 changes: 31 additions & 5 deletions test/openjd/adaptor_runtime/unit/background/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@

import dataclasses

from enum import Enum

import pytest

from openjd.adaptor_runtime._background.model import DataclassMapper


class StrEnum(str, Enum):
TEST = "test_str"
TEST_UNI = "test_☃"


class NormalEnum(Enum):
ONE = 1


# Define two dataclasses to use for tests
@dataclasses.dataclass
class Inner:
Expand All @@ -17,6 +28,9 @@ class Inner:
class Outer:
outer_key: str
inner: Inner
test_str: StrEnum
test_str_unicode: StrEnum
normal_enum: NormalEnum


class TestDataclassMapper:
Expand All @@ -26,17 +40,29 @@ class TestDataclassMapper:

def test_maps_nested_dataclass(self):
# GIVEN
input = {"outer_key": "outer_value", "inner": {"key": "value"}}
input = {
"outer_key": "outer_value",
"inner": {
"key": "value",
},
"test_str": "test_str",
"test_str_unicode": "test_☃",
"normal_enum": 1,
}
mapper = DataclassMapper(Outer)

# WHEN
result = mapper.map(input)

# THEN
assert isinstance(result, Outer)
assert isinstance(result.inner, Inner)
assert result.outer_key == "outer_value"
assert result.inner.key == "value"
expected_dataclass = Outer(
outer_key="outer_value",
inner=Inner(key="value"),
test_str=StrEnum.TEST,
test_str_unicode=StrEnum.TEST_UNI,
normal_enum=NormalEnum.ONE,
)
assert result == expected_dataclass

def test_raises_when_field_is_missing(self):
# GIVEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def test_graceful_shutdown(self) -> None:

# To avoid a race condition, giving some extra time for the logging subprocess to start.
_sleep(0.5 if OSName.is_posix() else 4)
signal_type: signal.Signals
if OSName.is_windows():
signal_type = signal.CTRL_BREAK_EVENT # type: ignore[attr-defined]
else:
Expand Down Expand Up @@ -77,6 +78,7 @@ def test_client_in_thread_does_not_do_graceful_shutdown(self) -> None:

# To avoid a race condition, giving some extra time for the logging subprocess to start.
_sleep(0.5 if OSName.is_posix() else 4)
signal_type: signal.Signals
if OSName.is_windows():
signal_type = signal.CTRL_BREAK_EVENT # type: ignore[attr-defined]
else:
Expand Down