Skip to content

Commit dd694cb

Browse files
committed
Merge remote-tracking branch 'origin/0.6.0' into 283-create-rabbitmq-plugin
2 parents 69b7668 + 1e830fd commit dd694cb

File tree

98 files changed

+2732
-622
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+2732
-622
lines changed

packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_pg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def build_event_repository(self) -> EventRepository:
4444
return PostgreSqlEventRepository(**self.repository_db)
4545

4646
def test_constructor(self):
47-
repository = PostgreSqlEventRepository("host", 1234, "database", "user", "password")
47+
repository = PostgreSqlEventRepository("database", "host", 1234, "user", "password")
4848
self.assertIsInstance(repository, EventRepository)
4949
self.assertEqual("host", repository.host)
5050
self.assertEqual(1234, repository.port)

packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_pg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async def test_subclass(self) -> None:
4343
self.assertTrue(issubclass(PostgreSqlTransactionRepository, TransactionRepository))
4444

4545
def test_constructor(self):
46-
repository = PostgreSqlTransactionRepository("host", 1234, "database", "user", "password")
46+
repository = PostgreSqlTransactionRepository("database", "host", 1234, "user", "password")
4747
self.assertIsInstance(repository, PostgreSqlTransactionRepository)
4848
self.assertEqual("host", repository.host)
4949
self.assertEqual(1234, repository.port)

packages/core/minos-microservice-aggregate/tests/utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,20 @@ def setUp(self) -> None:
7373
self.snapshot_repository,
7474
],
7575
)
76-
self.injector.wire()
76+
self.injector.wire_injections()
7777

7878
async def asyncSetUp(self):
7979
await super().asyncSetUp()
8080

81-
await self.injector.setup()
81+
await self.injector.setup_injections()
8282

8383
async def asyncTearDown(self):
84-
await self.injector.destroy()
84+
await self.injector.destroy_injections()
8585

8686
await super().asyncTearDown()
8787

8888
def tearDown(self) -> None:
89-
self.injector.unwire()
89+
self.injector.unwire_injections()
9090
super().tearDown()
9191

9292

packages/core/minos-microservice-common/minos/common/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
__version__ = "0.5.3"
44

55
from .builders import (
6+
BuildableMixin,
67
Builder,
78
)
89
from .config import (
910
Config,
1011
ConfigV1,
12+
ConfigV2,
1113
MinosConfig,
1214
)
1315
from .database import (

packages/core/minos-microservice-common/minos/common/builders.py

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
from abc import (
66
ABC,
7-
abstractmethod,
87
)
98
from typing import (
109
Any,
1110
Generic,
11+
Optional,
1212
TypeVar,
13+
Union,
14+
get_args,
1315
)
1416

1517
from .config import (
@@ -25,25 +27,50 @@
2527
class Builder(SetupMixin, ABC, Generic[Instance]):
2628
"""Builder class."""
2729

28-
def __init__(self, *args, **kwargs):
30+
def __init__(self, instance_cls: Optional[type[Instance]] = None, *args, **kwargs):
31+
2932
super().__init__(*args, **kwargs)
33+
if instance_cls is None:
34+
instance_cls = self._get_cls()
35+
3036
self.kwargs = dict()
37+
self.instance_cls = instance_cls
38+
39+
def _get_cls(self) -> Optional[type]:
40+
# noinspection PyUnresolvedReferences
41+
bases = self.__orig_bases__
42+
43+
instance_cls = get_args(next((base for base in bases if len(get_args(base))), None))[0]
44+
45+
if not isinstance(instance_cls, type):
46+
return None
47+
48+
return instance_cls
3149

3250
def copy(self: type[B]) -> B:
3351
"""Get a copy of the instance.
3452
35-
:return: A ``BrokerSubscriberBuilder`` instance.
53+
:return: A ``Builder`` instance.
3654
"""
37-
return self.new().with_kwargs(self.kwargs)
55+
return self.new().with_cls(self.instance_cls).with_kwargs(self.kwargs)
3856

3957
@classmethod
4058
def new(cls: type[B]) -> B:
4159
"""Get a new instance.
4260
43-
:return: A ``BrokerSubscriberBuilder`` instance.
61+
:return: A ``Builder`` instance.
4462
"""
4563
return cls()
4664

65+
def with_cls(self: B, cls: type) -> B:
66+
"""Set class to be built.
67+
68+
:param cls: The class to be set.
69+
:return: This method return the builder instance.
70+
"""
71+
self.instance_cls = cls
72+
return self
73+
4774
def with_kwargs(self: B, kwargs: dict[str, Any]) -> B:
4875
"""Set kwargs.
4976
@@ -62,12 +89,58 @@ def with_config(self: B, config: Config) -> B:
6289
"""
6390
return self
6491

65-
@abstractmethod
6692
def build(self) -> Instance:
6793
"""Build the instance.
6894
69-
:return: A ``BrokerSubscriber`` instance.
95+
:return: A ``Instance`` instance.
7096
"""
97+
return self.instance_cls(**self.kwargs)
98+
99+
def __eq__(self, other: Any) -> bool:
100+
return isinstance(other, type(self)) and self.instance_cls == other.instance_cls and self.kwargs == other.kwargs
101+
102+
def __repr__(self) -> str:
103+
return f"{type(self).__name__}({self.instance_cls.__name__}, {self.kwargs!r})"
104+
105+
106+
Ins = TypeVar("Ins", bound="BuildableMixin")
107+
108+
109+
class BuildableMixin(SetupMixin):
110+
"""Buildable Mixin class."""
111+
112+
_builder: Union[Builder[Ins], type[Builder[Ins]]] = Builder
113+
114+
@classmethod
115+
def _from_config(cls, config: Config, **kwargs):
116+
return cls.get_builder().with_config(config).with_kwargs(kwargs).build()
117+
118+
@classmethod
119+
def set_builder(cls: type[Ins], builder: Union[Builder[Ins], type[Builder[Ins]]]) -> None:
120+
"""Set a builder class.
121+
122+
:param builder: The builder class to be set.
123+
:return: This method does not return anything.
124+
"""
125+
if not isinstance(builder, Builder) and not (isinstance(builder, type) and issubclass(builder, Builder)):
126+
raise ValueError(f"Given builder value is invalid: {builder!r}")
127+
128+
cls._builder = builder
129+
130+
@classmethod
131+
def get_builder(cls) -> Builder[Ins]:
132+
"""Get the builder class.
133+
134+
:return: A ``Builder`` instance.
135+
"""
136+
builder = cls._builder
137+
138+
if isinstance(builder, Builder):
139+
builder = builder.copy()
140+
else:
141+
builder = builder.new()
142+
143+
return builder.with_cls(cls)
71144

72145

73146
B = TypeVar("B", bound=Builder)

packages/core/minos-microservice-common/minos/common/config/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
from .v1 import (
66
ConfigV1,
77
)
8+
from .v2 import (
9+
ConfigV2,
10+
)

packages/core/minos-microservice-common/minos/common/config/abc.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414
from collections.abc import (
1515
Callable,
1616
)
17+
from contextlib import (
18+
suppress,
19+
)
1720
from pathlib import (
1821
Path,
1922
)
2023
from typing import (
2124
TYPE_CHECKING,
2225
Any,
26+
Optional,
2327
Union,
2428
)
2529

@@ -40,16 +44,17 @@
4044
InjectableMixin,
4145
)
4246

47+
sentinel = object()
48+
4349

4450
@Injectable("config")
4551
class Config(ABC):
4652
"""Config base class."""
4753

48-
_PARAMETERIZED_MAPPER: dict = dict()
49-
_ENVIRONMENT_MAPPER: dict = dict()
50-
5154
__slots__ = ("_file_path", "_data", "_with_environment", "_parameterized")
5255

56+
DEFAULT_VALUES: dict[str, Any] = dict()
57+
5358
def __init__(self, path: Union[Path, str], with_environment: bool = True, **kwargs):
5459
super().__init__()
5560
if isinstance(path, str):
@@ -68,11 +73,15 @@ def __new__(cls, *args, **kwargs) -> Config:
6873
from .v1 import (
6974
ConfigV1,
7075
)
76+
from .v2 import (
77+
ConfigV2,
78+
)
7179

7280
version_mapper = defaultdict(
7381
lambda: ConfigV1,
7482
{
7583
1: ConfigV1,
84+
2: ConfigV2,
7685
},
7786
)
7887

@@ -185,6 +194,17 @@ def get_interfaces(self) -> dict[str, dict[str, Any]]:
185194
def _get_interfaces(self) -> dict[str, dict[str, Any]]:
186195
raise NotImplementedError
187196

197+
def get_pools(self) -> dict[str, type]:
198+
"""Get the pools value.
199+
200+
:return: A ``dict`` with pool names as keys and pools as values.
201+
"""
202+
return self._get_pools()
203+
204+
@abstractmethod
205+
def _get_pools(self) -> dict[str, type]:
206+
raise NotImplementedError
207+
188208
def get_routers(self) -> list[type]:
189209
"""Get the routers value.
190210
@@ -266,26 +286,54 @@ def get_by_key(self, key: str) -> Any:
266286
:param key: The key that identifies the value.
267287
:return: A value instance.
268288
"""
269-
if key in self._PARAMETERIZED_MAPPER and self._PARAMETERIZED_MAPPER[key] in self._parameterized:
270-
return self._parameterized[self._PARAMETERIZED_MAPPER[key]]
271289

272-
if self._with_environment and key in self._ENVIRONMENT_MAPPER and self._ENVIRONMENT_MAPPER[key] in os.environ:
273-
return os.environ[self._ENVIRONMENT_MAPPER[key]]
290+
def _fn(k: str, data: dict[str, Any], previous: str = "", default: Optional[Any] = sentinel) -> Any:
291+
current, _sep, following = k.partition(".")
292+
full = f"{previous}.{current}".lstrip(".")
293+
294+
with suppress(KeyError):
295+
return self._parameterized[self._to_parameterized_variable(full)]
296+
297+
if self._with_environment:
298+
with suppress(KeyError):
299+
return os.environ[self._to_environment_variable(full)]
300+
301+
if default is not sentinel and current in default:
302+
default_part = default[current]
303+
else:
304+
default_part = sentinel
274305

275-
def _fn(k: str, data: dict[str, Any]) -> Any:
276-
current, _, following = k.partition(".")
306+
if current not in data and default_part is not sentinel:
307+
part = default_part
308+
else:
309+
part = data[current]
277310

278-
part = data[current]
279-
if not following:
311+
if following:
312+
return _fn(following, part, full, default_part)
313+
314+
if not isinstance(part, dict):
280315
return part
281316

282-
return _fn(following, part)
317+
keys = part.keys()
318+
if isinstance(default_part, dict):
319+
keys |= default_part.keys()
320+
321+
result = dict()
322+
for subpart in keys:
323+
result[subpart] = _fn(subpart, part, full, default_part)
324+
return result
283325

284326
try:
285-
return _fn(key, self._data)
327+
return _fn(key, self._data, default=self.DEFAULT_VALUES)
286328
except Exception:
287329
raise MinosConfigException(f"{key!r} field is not defined on the configuration!")
288330

331+
def _to_parameterized_variable(self, key: str) -> str:
332+
raise KeyError
333+
334+
def _to_environment_variable(self, key: str) -> str:
335+
raise KeyError
336+
289337

290338
# noinspection PyUnusedLocal
291339
def _get_version(path: Union[str, Path], *args, **kwargs) -> int:

0 commit comments

Comments
 (0)