python-hexagonal 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hexagonal/__init__.py +2 -0
- hexagonal/adapters/drivens/buses/base/__init__.py +15 -0
- hexagonal/adapters/drivens/buses/base/command_bus.py +69 -0
- hexagonal/adapters/drivens/buses/base/event_bus.py +160 -0
- hexagonal/adapters/drivens/buses/base/infrastructure.py +38 -0
- hexagonal/adapters/drivens/buses/base/message_bus.py +73 -0
- hexagonal/adapters/drivens/buses/base/query.py +82 -0
- hexagonal/adapters/drivens/buses/base/utils.py +1 -0
- hexagonal/adapters/drivens/buses/inmemory/__init__.py +12 -0
- hexagonal/adapters/drivens/buses/inmemory/command_bus.py +70 -0
- hexagonal/adapters/drivens/buses/inmemory/event_bus.py +69 -0
- hexagonal/adapters/drivens/buses/inmemory/infra.py +49 -0
- hexagonal/adapters/drivens/mappers.py +127 -0
- hexagonal/adapters/drivens/repository/base/__init__.py +13 -0
- hexagonal/adapters/drivens/repository/base/repository.py +85 -0
- hexagonal/adapters/drivens/repository/base/unit_of_work.py +75 -0
- hexagonal/adapters/drivens/repository/sqlite/__init__.py +18 -0
- hexagonal/adapters/drivens/repository/sqlite/datastore.py +197 -0
- hexagonal/adapters/drivens/repository/sqlite/env_vars.py +2 -0
- hexagonal/adapters/drivens/repository/sqlite/infrastructure.py +20 -0
- hexagonal/adapters/drivens/repository/sqlite/outbox.py +405 -0
- hexagonal/adapters/drivens/repository/sqlite/repository.py +286 -0
- hexagonal/adapters/drivens/repository/sqlite/unit_of_work.py +25 -0
- hexagonal/adapters/drivers/__init__.py +5 -0
- hexagonal/adapters/drivers/app.py +38 -0
- hexagonal/application/__init__.py +29 -0
- hexagonal/application/api.py +61 -0
- hexagonal/application/app.py +76 -0
- hexagonal/application/bus_app.py +70 -0
- hexagonal/application/handlers.py +107 -0
- hexagonal/application/infrastructure.py +64 -0
- hexagonal/application/query.py +71 -0
- hexagonal/domain/__init__.py +77 -0
- hexagonal/domain/aggregate.py +159 -0
- hexagonal/domain/base.py +169 -0
- hexagonal/domain/exceptions.py +38 -0
- hexagonal/entrypoints/__init__.py +4 -0
- hexagonal/entrypoints/app.py +53 -0
- hexagonal/entrypoints/base.py +105 -0
- hexagonal/entrypoints/bus.py +68 -0
- hexagonal/entrypoints/sqlite.py +49 -0
- hexagonal/ports/__init__.py +0 -0
- hexagonal/ports/drivens/__init__.py +43 -0
- hexagonal/ports/drivens/application.py +35 -0
- hexagonal/ports/drivens/buses.py +148 -0
- hexagonal/ports/drivens/infrastructure.py +19 -0
- hexagonal/ports/drivens/repository.py +152 -0
- hexagonal/ports/drivers/__init__.py +3 -0
- hexagonal/ports/drivers/app.py +58 -0
- hexagonal/py.typed +0 -0
- python_hexagonal-0.1.0.dist-info/METADATA +15 -0
- python_hexagonal-0.1.0.dist-info/RECORD +53 -0
- python_hexagonal-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Generic, Iterable
|
|
3
|
+
|
|
4
|
+
from hexagonal.domain import (
|
|
5
|
+
CloudMessage,
|
|
6
|
+
QueryResults,
|
|
7
|
+
TEvento,
|
|
8
|
+
TMessagePayloadType,
|
|
9
|
+
TQuery,
|
|
10
|
+
TView,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .repository import ISearchRepository, TManager
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class IUseCase(ABC):
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def execute(self) -> Iterable[TEvento]: ...
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class IMessageHandler(ABC, Generic[TMessagePayloadType]):
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def handle_message(self, message: CloudMessage[TMessagePayloadType]) -> None: ...
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def get_use_case(self, message: TMessagePayloadType) -> IUseCase: ...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class IQueryHandler(ABC, Generic[TManager, TQuery, TView]):
|
|
30
|
+
@property
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def repository(self) -> ISearchRepository[TManager, TQuery, TView]: ...
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def get(self, query: TQuery) -> QueryResults[TView]: ...
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Callable, Generic, Literal, Type, overload
|
|
3
|
+
|
|
4
|
+
from hexagonal.domain import (
|
|
5
|
+
CloudMessage,
|
|
6
|
+
Query,
|
|
7
|
+
QueryResult,
|
|
8
|
+
QueryResults,
|
|
9
|
+
TCommand,
|
|
10
|
+
TEvent,
|
|
11
|
+
TQuery,
|
|
12
|
+
TView,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from .application import IMessageHandler, IQueryHandler
|
|
16
|
+
from .infrastructure import IBaseInfrastructure
|
|
17
|
+
from .repository import IInboxRepository, IOutboxRepository, TManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class IBaseMessageBus(IBaseInfrastructure, ABC, Generic[TManager]):
|
|
21
|
+
@property
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def inbox_repository(self) -> IInboxRepository[TManager]: ...
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def outbox_repository(self) -> IOutboxRepository[TManager]: ...
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def publish_from_outbox(self, limit: int | None = None):
|
|
31
|
+
"""Publicar mensajes desde la outbox., hasta el límite especificado."""
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def consume(self, limit: int | None = None):
|
|
36
|
+
"""Consumir mensajes desde la inbox, hasta el límite especificado."""
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ICommandBus(IBaseMessageBus[TManager], ABC):
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def register_handler(
|
|
43
|
+
self, command_type: Type[TCommand], handler: IMessageHandler[TCommand]
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Registrar un manejador para un tipo de comando."""
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def unregister_handler(self, command_type: Type[TCommand]) -> None:
|
|
50
|
+
"""Desregistrar el manejador para un tipo de comando."""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def dispatch(
|
|
55
|
+
self,
|
|
56
|
+
command: TCommand | CloudMessage[TCommand],
|
|
57
|
+
*,
|
|
58
|
+
to_outbox: bool = False,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Despachar un comando para su procesamiento."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def process_command(self, command: CloudMessage[TCommand]) -> None:
|
|
65
|
+
"""Procesar un comando recibido."""
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class IEventBus(IBaseMessageBus[TManager], ABC):
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def subscribe(self, event_type: Type[TEvent], handler: IMessageHandler[TEvent]):
|
|
72
|
+
"""Suscribir un manejador a un tipo de evento."""
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def unsubscribe(
|
|
77
|
+
self,
|
|
78
|
+
event_type: Type[TEvent],
|
|
79
|
+
*handlers: IMessageHandler[TEvent],
|
|
80
|
+
): ...
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
def publish(self, *events: CloudMessage[TEvent]) -> None:
|
|
84
|
+
"""Publicar un evento a todos sus suscriptores."""
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def process_events(self, *events: CloudMessage[TEvent]) -> None: ...
|
|
89
|
+
|
|
90
|
+
# wait for
|
|
91
|
+
@overload
|
|
92
|
+
def wait_for_publish(
|
|
93
|
+
self, event_type: Type[TEvent], handler: Callable[[TEvent], None]
|
|
94
|
+
) -> None: ...
|
|
95
|
+
@overload
|
|
96
|
+
def wait_for_publish(
|
|
97
|
+
self, event_type: Type[TEvent]
|
|
98
|
+
) -> Callable[[Callable[[TEvent], None]], None]: ...
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
def wait_for_publish(
|
|
102
|
+
self, event_type: Type[TEvent], handler: Callable[[TEvent], None] | None = None
|
|
103
|
+
) -> Callable[[Callable[[TEvent], None]], None] | None: ...
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class IQueryBus(IBaseInfrastructure, Generic[TManager]):
|
|
107
|
+
@abstractmethod
|
|
108
|
+
def register_handler(
|
|
109
|
+
self,
|
|
110
|
+
query_type: Type[TQuery],
|
|
111
|
+
handler: IQueryHandler[TManager, TQuery, TView],
|
|
112
|
+
): ...
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def unregister_handler(self, query_type: Type[Query[TView]]): ...
|
|
116
|
+
|
|
117
|
+
@overload
|
|
118
|
+
def get(self, query: Query[TView], *, one: Literal[True]) -> QueryResult[TView]: ...
|
|
119
|
+
|
|
120
|
+
@overload
|
|
121
|
+
def get(
|
|
122
|
+
self,
|
|
123
|
+
query: Query[TView],
|
|
124
|
+
*,
|
|
125
|
+
one: Literal[False] = False,
|
|
126
|
+
) -> QueryResults[TView]: ...
|
|
127
|
+
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def get(
|
|
130
|
+
self,
|
|
131
|
+
query: Query[TView],
|
|
132
|
+
*,
|
|
133
|
+
one: bool = False,
|
|
134
|
+
) -> QueryResult[TView] | QueryResults[TView]: ...
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class IBusInfrastructure(IBaseInfrastructure, Generic[TManager]):
|
|
138
|
+
@property
|
|
139
|
+
@abstractmethod
|
|
140
|
+
def command_bus(self) -> ICommandBus[TManager]: ...
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
@abstractmethod
|
|
144
|
+
def event_bus(self) -> IEventBus[TManager]: ...
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def query_bus(self) -> IQueryBus[TManager]: ...
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Mapping
|
|
3
|
+
|
|
4
|
+
from hexagonal.domain import InfrastructureNotInitialized
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IBaseInfrastructure(ABC):
|
|
8
|
+
@property
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def initialized(self) -> bool: ...
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def initialize(self, env: Mapping[str, str]) -> None: ...
|
|
14
|
+
|
|
15
|
+
def verify(self):
|
|
16
|
+
if not self.initialized:
|
|
17
|
+
raise InfrastructureNotInitialized(
|
|
18
|
+
f"{self.__class__.__name__} is not initialized"
|
|
19
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from typing import Any, Generic, List, Self, TypeVar
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from hexagonal.domain import (
|
|
7
|
+
AggregateRoot,
|
|
8
|
+
CloudMessage,
|
|
9
|
+
TIdEntity,
|
|
10
|
+
TQuery,
|
|
11
|
+
TView,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from .infrastructure import IBaseInfrastructure
|
|
15
|
+
|
|
16
|
+
TAggregate = TypeVar("TAggregate", bound=AggregateRoot[Any, Any])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IConnectionManager(IBaseInfrastructure, ABC):
|
|
20
|
+
@contextmanager
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def start_connection(self) -> Any: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
TManager = TypeVar("TManager", bound=IConnectionManager)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class IBaseRepository(IBaseInfrastructure, Generic[TManager]):
|
|
29
|
+
@property
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def connection_manager(self) -> TManager: ...
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def attach_to_unit_of_work(self, uow: "IUnitOfWork[TManager]") -> None: ...
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def detach_from_unit_of_work(self) -> None: ...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class IUnitOfWork(IBaseInfrastructure, ABC, Generic[TManager]):
|
|
41
|
+
@property
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def connection_manager(self) -> TManager: ...
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def commit(self) -> None: ...
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def rollback(self) -> None: ...
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def attach_repo(self, repo: IBaseRepository[TManager]) -> None: ...
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def detach_repo(self, repo: IBaseRepository[TManager]) -> None: ...
|
|
56
|
+
|
|
57
|
+
def __enter__(self) -> Self:
|
|
58
|
+
return self
|
|
59
|
+
|
|
60
|
+
def __exit__(self, exc_type, exc_val, exc_tb): # type: ignore
|
|
61
|
+
if exc_type is None:
|
|
62
|
+
self.commit()
|
|
63
|
+
else:
|
|
64
|
+
self.rollback()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class IAggregateRepository(
|
|
68
|
+
IBaseRepository[TManager],
|
|
69
|
+
Generic[TManager, TAggregate, TIdEntity],
|
|
70
|
+
):
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def save(self, aggregate: TAggregate) -> None:
|
|
73
|
+
"""Persistir el agregado en el almacenamiento."""
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def get(self, id: TIdEntity) -> TAggregate:
|
|
78
|
+
"""Recuperar el agregado por su ID."""
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def delete(self, id: TIdEntity) -> TAggregate:
|
|
83
|
+
"""Eliminar el agregado por su ID."""
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class IOutboxRepository(IBaseRepository[TManager]):
|
|
88
|
+
"""Puerto para manejar eventos pendientes de publicar (write-side)."""
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def save(self, *message: CloudMessage[Any]) -> None:
|
|
92
|
+
"""Guardar evento en la tabla Outbox en la misma transacción del agregado."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
@abstractmethod
|
|
96
|
+
def fetch_pending(self, limit: int | None = None) -> list[CloudMessage[Any]]:
|
|
97
|
+
"""Recuperar eventos no publicados aún."""
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
def mark_as_published(self, *message_ids: UUID) -> None:
|
|
102
|
+
"""Marcar un evento como publicado correctamente."""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
@abstractmethod
|
|
106
|
+
def mark_as_failed(self, *message_ids: UUID, error: str) -> None:
|
|
107
|
+
"""Incrementar intentos o marcar el evento como fallido."""
|
|
108
|
+
...
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class IInboxRepository(IBaseRepository[TManager]):
|
|
112
|
+
"""Puerto para procesar mensajes de entrada de forma idempotente."""
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def register_message(
|
|
116
|
+
self,
|
|
117
|
+
message: CloudMessage[Any],
|
|
118
|
+
handler: str,
|
|
119
|
+
max_retries: int = 3,
|
|
120
|
+
) -> bool:
|
|
121
|
+
"""
|
|
122
|
+
Intenta registrar un mensaje.
|
|
123
|
+
Retorna False si ya existe (duplicado).
|
|
124
|
+
"""
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
@abstractmethod
|
|
128
|
+
def mark_as_processed(self, message_id: UUID, handler: str) -> None:
|
|
129
|
+
"""Marcar el mensaje como procesado exitosamente."""
|
|
130
|
+
...
|
|
131
|
+
|
|
132
|
+
@abstractmethod
|
|
133
|
+
def mark_as_failed(self, message_id: UUID, handler: str, error: str) -> None:
|
|
134
|
+
"""Marcar el mensaje como fallido."""
|
|
135
|
+
...
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class ISearchRepository(IBaseRepository[TManager], Generic[TManager, TQuery, TView]):
|
|
139
|
+
@abstractmethod
|
|
140
|
+
def search(self, query: TQuery) -> List[TView]:
|
|
141
|
+
"""Buscar objetos de valor según el query proporcionado."""
|
|
142
|
+
...
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class IPairInboxOutbox(IBaseInfrastructure, Generic[TManager]):
|
|
146
|
+
@property
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def inbox(self) -> IInboxRepository[TManager]: ...
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
@abstractmethod
|
|
152
|
+
def outbox(self) -> IOutboxRepository[TManager]: ...
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from hexagonal.domain import CloudMessage, TCommand, TEvent
|
|
5
|
+
from hexagonal.ports.drivens import (
|
|
6
|
+
IBusInfrastructure,
|
|
7
|
+
ICommandBus,
|
|
8
|
+
IEventBus,
|
|
9
|
+
IQueryBus,
|
|
10
|
+
IUnitOfWork,
|
|
11
|
+
TManager,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IBusApp(ABC, Generic[TManager]):
|
|
16
|
+
@property
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def uow(self) -> IUnitOfWork[TManager]: ...
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def bootstrap(
|
|
22
|
+
self,
|
|
23
|
+
command_bus: ICommandBus[TManager],
|
|
24
|
+
query_bus: IQueryBus[TManager],
|
|
25
|
+
event_bus: IEventBus[TManager],
|
|
26
|
+
) -> None: ...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class IBaseApplication(ABC, Generic[TManager]):
|
|
30
|
+
@property
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def bus_app(self) -> IBusApp[TManager]: ...
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def bus_infrastructure(self) -> IBusInfrastructure[TManager]: ...
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def command_bus(self) -> ICommandBus[TManager]: ...
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def query_bus(self) -> IQueryBus[TManager]: ...
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def event_bus(self) -> IEventBus[TManager]: ...
|
|
49
|
+
|
|
50
|
+
@abstractmethod
|
|
51
|
+
def bootstrap(self, bus_app: IBusApp[TManager]) -> None: ...
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def dispatch_and_wait_events(
|
|
55
|
+
self,
|
|
56
|
+
command: CloudMessage[TCommand],
|
|
57
|
+
*event_types: type[TEvent],
|
|
58
|
+
) -> dict[type[TEvent], TEvent | None]: ...
|
hexagonal/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: python-hexagonal
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Framework to build hexagonal architecture applications in Python.
|
|
5
|
+
Author: jose-matos-9281
|
|
6
|
+
Author-email: jose-matos-9281 <58991817+jose-matos-9281@users.noreply.github.com>
|
|
7
|
+
Requires-Dist: eventsourcing>=9.4.6
|
|
8
|
+
Requires-Dist: orjson>=3.11.5
|
|
9
|
+
Requires-Dist: pydantic>=2.12.5
|
|
10
|
+
Requires-Dist: uuid6>=2025.0.1
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# python-hexagonal
|
|
15
|
+
Framework of Ports and adapters Architecture, applying concepts of DDD
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
hexagonal/__init__.py,sha256=4GlVYmzCh2BmPst6WpxxqraLcfXmlbyrGcNFyi28dng,62
|
|
2
|
+
hexagonal/adapters/drivens/buses/base/__init__.py,sha256=3RM8lIIh4425-Ixnu_v667sdM6iAwDqds3GNUAANp5M,380
|
|
3
|
+
hexagonal/adapters/drivens/buses/base/command_bus.py,sha256=RhUcObspthpq4NUEooFXIV0p81FS5KsnJ3G3M0MGjFw,2226
|
|
4
|
+
hexagonal/adapters/drivens/buses/base/event_bus.py,sha256=jIDuipRaO7MT7oE0M3e8ALSmqe-YnFAVgTqqbHwUXqg,5743
|
|
5
|
+
hexagonal/adapters/drivens/buses/base/infrastructure.py,sha256=4x36U57kP4yk7YKGGmkQIB10JPmTFSgnaMx5OUDmeWU,965
|
|
6
|
+
hexagonal/adapters/drivens/buses/base/message_bus.py,sha256=aR90tALUSqV_vVTFBG0KGRXJnbi7I4OQ-29cCkTDuUo,2591
|
|
7
|
+
hexagonal/adapters/drivens/buses/base/query.py,sha256=eElI9zbfdQ7iSaSrR2sykdyKW1wBoLj86ngZzGHb40w,2424
|
|
8
|
+
hexagonal/adapters/drivens/buses/base/utils.py,sha256=w1qdMpddZph2sl-S2ir_ym23Rkq9fC9MEBvJ9PB3QpU,48
|
|
9
|
+
hexagonal/adapters/drivens/buses/inmemory/__init__.py,sha256=ySzpKqMKT7zc77M7AXOlGU9y8l0ZkHQ0We4wkxjuyzM,405
|
|
10
|
+
hexagonal/adapters/drivens/buses/inmemory/command_bus.py,sha256=gMyk-VNSDk_gk5ihP3cUQcfNIgqmLD1Nt-yzuTB9Uy4,2271
|
|
11
|
+
hexagonal/adapters/drivens/buses/inmemory/event_bus.py,sha256=xe-I4nBs2BE-vLVawRW3lXhBlW54X-XUjL9kRnX-hE0,2288
|
|
12
|
+
hexagonal/adapters/drivens/buses/inmemory/infra.py,sha256=Gkjx8ZUlg5jWbSXgg64-Hgrtegbmi-mcoI0T9oEkq0U,1336
|
|
13
|
+
hexagonal/adapters/drivens/mappers.py,sha256=15n1SGJ0RCGtsxPrOyNcnD2qpA-YYFCUWeA3Y1_4ric,4810
|
|
14
|
+
hexagonal/adapters/drivens/repository/base/__init__.py,sha256=MZoFzptMLTIMRxjxswbj3T3vDepu4KW07fwrKRYaKDU,270
|
|
15
|
+
hexagonal/adapters/drivens/repository/base/repository.py,sha256=_SC_mR65CX39boAeUnDCFAaUj1duYPtsi2CrpmpSOGM,2728
|
|
16
|
+
hexagonal/adapters/drivens/repository/base/unit_of_work.py,sha256=xRn_kvbv_FYo6FDNvSDYYUuIFYeoUo7AMapyYBAzbjo,2496
|
|
17
|
+
hexagonal/adapters/drivens/repository/sqlite/__init__.py,sha256=0Uzaw2atFFfjQ1ppgtKQD39YwmiEl-O9nqUI30Bww20,598
|
|
18
|
+
hexagonal/adapters/drivens/repository/sqlite/datastore.py,sha256=N0r8v4slYFtIXGMBPuf1_AvqkAaayCXYQfzdDDMcrT4,7028
|
|
19
|
+
hexagonal/adapters/drivens/repository/sqlite/env_vars.py,sha256=EXRbG3NlTQg3rnUUszW0IDGuQLi_Grbd2uXIX3V4mJA,88
|
|
20
|
+
hexagonal/adapters/drivens/repository/sqlite/infrastructure.py,sha256=hQmogShv99cUF4PSgZlkn0BcCEMydWt0hxDREEfG5u8,736
|
|
21
|
+
hexagonal/adapters/drivens/repository/sqlite/outbox.py,sha256=FdEllWC2-tMHJ3-gboHQCH7iDYtlVWeYXN6KKUC3gJc,14125
|
|
22
|
+
hexagonal/adapters/drivens/repository/sqlite/repository.py,sha256=IRs9Mm_rBD-pE_D7OWlvvJgxW5WrvAHhdAz3jZgJA_k,10271
|
|
23
|
+
hexagonal/adapters/drivens/repository/sqlite/unit_of_work.py,sha256=2yoP7U_WTgK6mzMtaAEcoV2hmgNNgNjT3vpxzWT8c0A,907
|
|
24
|
+
hexagonal/adapters/drivers/__init__.py,sha256=tHcyqkut5K7LvlDT1QVJ3N7Z1UrmfqNYuKjlrxitoAc,87
|
|
25
|
+
hexagonal/adapters/drivers/app.py,sha256=3MuDI2cl1TauoBk4qVDAOWik4dGiekUYkHPZbCCCPeE,1124
|
|
26
|
+
hexagonal/application/__init__.py,sha256=IvGbZfRqI3hUA8SXn_YhSgwcyrQg9RFrgi3XtAWFV9Q,752
|
|
27
|
+
hexagonal/application/api.py,sha256=YQVRAENQVtMOSPZgjWPNUaEgennPtnPN3A2XjBEdbd4,2152
|
|
28
|
+
hexagonal/application/app.py,sha256=OBsJ5dPp9hdO-aKDKhdMI-PMP5UHTyadA0xAcYzq-EQ,2404
|
|
29
|
+
hexagonal/application/bus_app.py,sha256=Ubwy5HKDOi1vJWT0LsEm0y1vM53ROZLbHGEw72S7eYw,1995
|
|
30
|
+
hexagonal/application/handlers.py,sha256=sAirS7Fa9o5UAPamfLz0gU1ZpyEaeqCyB6qdqlweGfU,3011
|
|
31
|
+
hexagonal/application/infrastructure.py,sha256=KGKnVUkFCxZvlv1mySaunzFqXX9Kvh_XP-pfueU4jc8,2047
|
|
32
|
+
hexagonal/application/query.py,sha256=Td7BvPUl_rvAL2Rnf2HS8hjtH1EpfIU9BUSYvTKmGJw,2150
|
|
33
|
+
hexagonal/domain/__init__.py,sha256=iVAzcLFU1A2KAeI0o-RUtp4OJdF4y4NoTmjgdtD1Bh8,1422
|
|
34
|
+
hexagonal/domain/aggregate.py,sha256=byVnwM9_JuRNYp7FHLWMOqryAQn0H9OvyEEtsDZPmAw,4763
|
|
35
|
+
hexagonal/domain/base.py,sha256=aLwbE1aQp3Cf6NO-fihuK7gS2Z-KO5jtfE7ZKAerBbs,4495
|
|
36
|
+
hexagonal/domain/exceptions.py,sha256=y1fX320cNoswgJg_W1rGowHM8XY1wg5f_kkTEWVcjOk,1275
|
|
37
|
+
hexagonal/entrypoints/__init__.py,sha256=Kh83vld6l4GXJEUN-LHegT2eYlq2pDvGhtO8jTCFq7s,139
|
|
38
|
+
hexagonal/entrypoints/app.py,sha256=JBxj_IAPrNevS8HY6zhUR7hiGy1P22nSShorYwEXbJM,2013
|
|
39
|
+
hexagonal/entrypoints/base.py,sha256=8r_s-TeD2Awzyctvx4K3UHZU5t5A2WZKmlEi0gOrjF0,3215
|
|
40
|
+
hexagonal/entrypoints/bus.py,sha256=pilgSDBxwG_hL_3MaqzrHTshO_TfNkU8OHtcBmdiPYk,2044
|
|
41
|
+
hexagonal/entrypoints/sqlite.py,sha256=akCp1bglcQSz-Xz2c3usPebCKD05zTzRbTSF9TMaX5s,1738
|
|
42
|
+
hexagonal/ports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
+
hexagonal/ports/drivens/__init__.py,sha256=wERGIFEpeZScrw73Co36QwjK_icnuvKbZ7Bj_whQyQ0,897
|
|
44
|
+
hexagonal/ports/drivens/application.py,sha256=9vxvR4yhwOklrtFlUZin8nmzj2xqc1Hvg5xForPBYKw,863
|
|
45
|
+
hexagonal/ports/drivens/buses.py,sha256=tCEFbzA1-R8UMum2Y2hyeGd2W6jYz4bR8PJniktdZhY,4024
|
|
46
|
+
hexagonal/ports/drivens/infrastructure.py,sha256=pMr9oF9mUta-hY6vv2DieQpANYCrPpwgwDQB1QMaxpc,494
|
|
47
|
+
hexagonal/ports/drivens/repository.py,sha256=ijewN8988N0FTEoVtWforyeBc0ejLzBX6mDPQjJ_XE8,4096
|
|
48
|
+
hexagonal/ports/drivers/__init__.py,sha256=cADln99MHC7KxZzLNc63q_VS53VSpAynvG4NUr2zDwY,86
|
|
49
|
+
hexagonal/ports/drivers/app.py,sha256=QJlNYGlpNcRPWlsNVTYXIwRNi1ggRdkqvo6ElFXAsUw,1368
|
|
50
|
+
hexagonal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
|
+
python_hexagonal-0.1.0.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
|
|
52
|
+
python_hexagonal-0.1.0.dist-info/METADATA,sha256=OF15AlgCDDholY0Dkj_UqE27KQutCVm5djK-eU-HA14,525
|
|
53
|
+
python_hexagonal-0.1.0.dist-info/RECORD,,
|