Skip to content

Commit 9e28789

Browse files
committed
init project
1 parent cc1c103 commit 9e28789

File tree

15 files changed

+367
-36
lines changed

15 files changed

+367
-36
lines changed

demo/python/generator/bo.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from typing import Any
2+
from iop import BusinessOperation
3+
4+
from msg import MyGeneratorResponse, MyGenerator # Import the generator message class
5+
6+
class MyGeneratorOperation(BusinessOperation):
7+
8+
def on_other_request(self, request: MyGeneratorResponse) -> Any:
9+
self.log_info("Received other request")
10+
return MyGeneratorResponse(my_other_string="Hello, World!")
11+
12+
def on_private_session_started(self, request: MyGenerator) -> Any:
13+
self.log_info("Private session started")
14+
return self.my_generator(request)
15+
16+
def my_generator(self, request: Any) -> Any:
17+
self.log_info(f"Processing request: {request}")
18+
# Simulate some processing and yield responses
19+
for i in range(5):
20+
response = f"Response {i} from MyGeneratorOperation"
21+
self.log_info(response)
22+
yield MyGeneratorResponse(my_other_string=response)
23+
24+

demo/python/generator/bp.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import Any
2+
from iop import BusinessProcess
3+
4+
from msg import MyGenerator, MyGeneratorResponse
5+
6+
class MyGeneratorProcess(BusinessProcess):
7+
8+
def on_request(self, request: Any) -> Any:
9+
rsp = self.send_request_sync(
10+
target="User.MyGeneratorOperation",
11+
request=MyGeneratorResponse(my_other_string="Hello, World!"),
12+
timeout=10,
13+
description="My generator request")
14+
gen = self.send_generator_request(
15+
target="User.MyGeneratorOperation",
16+
request=MyGenerator(my_string="Hello, World!"),
17+
timeout=10,
18+
description="My generator request")
19+
for response in gen:
20+
self.log_info(f"Received response: {response}")

demo/python/generator/msg.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from iop import GeneratorMessage,Message
2+
from dataclasses import dataclass
3+
4+
@dataclass
5+
class MyGenerator(GeneratorMessage):
6+
"""Base message to initialize generator function"""
7+
my_string: str
8+
9+
@dataclass
10+
class MyGeneratorResponse(Message):
11+
"""Base message to return generator function response"""
12+
my_other_string: str

demo/python/generator/settings.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from bo import MyGeneratorOperation
2+
from bp import MyGeneratorProcess
3+
4+
CLASSES = {
5+
"MyGeneratorOperation": MyGeneratorOperation,
6+
"MyGeneratorProcess": MyGeneratorProcess,
7+
}

src/iop/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from iop._business_service import _BusinessService
44
from iop._director import _Director
55
from iop._inbound_adapter import _InboundAdapter
6-
from iop._message import _Message, _PickleMessage, _PydanticMessage, _PydanticPickleMessage
6+
from iop._message import _Message, _PickleMessage, _PydanticMessage, _PydanticPickleMessage, _GeneratorMessage
77
from iop._outbound_adapter import _OutboundAdapter
88
from iop._private_session_duplex import _PrivateSessionDuplex
99
from iop._private_session_process import _PrivateSessionProcess
@@ -22,4 +22,5 @@ class Message(_Message): pass
2222
class PickleMessage(_PickleMessage): pass
2323
class PydanticMessage(_PydanticMessage): pass
2424
class PydanticPickleMessage(_PydanticPickleMessage): pass
25+
class GeneratorMessage(_GeneratorMessage): pass
2526
class Director(_Director): pass

src/iop/_business_host.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from ._decorators import input_serializer_param, output_deserializer
88
from ._dispatch import dispatch_serializer, dispatch_deserializer
99
from ._async_request import AsyncRequest
10+
from ._generator_request import _GeneratorRequest
1011

1112
class _BusinessHost(_Common):
1213
"""Base class for business components that defines common methods.
@@ -67,6 +68,22 @@ async def send_request_async_ng(self, target: str, request: Union[Message, Any],
6768
Response from target component
6869
"""
6970
return await AsyncRequest(target, request, timeout, description, self)
71+
72+
@input_serializer_param(1, 'request')
73+
def send_generator_request(self, target: str, request: Union[Message, Any],
74+
timeout: int = -1, description: Optional[str] = None) -> _GeneratorRequest:
75+
"""Send message as a generator request to target component.
76+
Args:
77+
target: Name of target component
78+
request: Message to send
79+
timeout: Timeout in seconds, -1 means wait forever
80+
description: Optional description for logging
81+
Returns:
82+
_GeneratorRequest: An instance of _GeneratorRequest to iterate over responses
83+
Raises:
84+
TypeError: If request is not of type Message or _GeneratorMessage
85+
"""
86+
return _GeneratorRequest(self, target, request, timeout, description)
7087

7188
def send_multi_request_sync(self, target_request: List[Tuple[str, Union[Message, Any]]],
7289
timeout: int = -1, description: Optional[str] = None) -> List[Tuple[str, Union[Message, Any], Any, int]]:

src/iop/_business_operation.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,34 @@ def OnMessage(self, request: Any) -> Any:
7272
The response object
7373
"""
7474
return
75+
76+
@input_deserializer
77+
@output_serializer
78+
def _dispatch_private_session_started(self, request: Any) -> Any:
79+
"""For internal use only."""
80+
self._gen = self.on_private_session_started(request)
81+
from . import _iris
82+
return _iris.get_iris().IOP.PrivateSession.Message.Ack._New()
83+
84+
def on_private_session_started(self, request: Any) -> Any:
85+
"""Called when a private session is started.
86+
87+
This method can be overridden to handle the start of a private session.
88+
89+
Args:
90+
request: The request object containing session details.
91+
92+
Returns:
93+
Any response object or None.
94+
"""
95+
return None
96+
97+
@input_serializer
98+
@output_deserializer
99+
def _dispatch_private_session_poll(self, request: Any) -> Any:
100+
"""For internal use only."""
101+
try:
102+
return next(self._gen)
103+
except StopIteration:
104+
import _iris
105+
return _iris.get_iris().IOP.PrivateSession.Message.Stop._New()

src/iop/_dispatch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from ._serialization import serialize_message, serialize_pickle_message, deserialize_message, deserialize_pickle_message
55
from ._message_validator import is_message_instance, is_pickle_message_instance, is_iris_object_instance
66

7+
from ._message import _GeneratorMessage
8+
79
def dispatch_serializer(message: Any) -> Any:
810
"""Serializes the message based on its type.
911
@@ -73,6 +75,9 @@ def dispach_message(host: Any, request: Any) -> Any:
7375
module = request.__class__.__module__
7476
classname = request.__class__.__name__
7577

78+
if isinstance(request, _GeneratorMessage):
79+
return getattr(host, '_dispatch_private_session_started')(request)
80+
7681
for msg, method in host.DISPATCH:
7782
if msg == module + "." + classname:
7883
call = method

src/iop/_generator_request.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import Any, Optional, Union
2+
3+
from . import _iris
4+
from ._message import _GeneratorMessage
5+
6+
7+
class _GeneratorRequest:
8+
"""Generator class to interetate over responses from a request.
9+
This class is used to handle the responses from a request in a generator-like manner."""
10+
11+
def __init__(self, host: Any, target: str, request: Union[_GeneratorMessage, Any],
12+
timeout: int = -1, description: Optional[str] = None) -> None:
13+
self.host = host
14+
self.target = target
15+
self.request = request
16+
self.timeout = timeout
17+
self.description = description
18+
self._response = None
19+
20+
# if not isinstance(self.request, _GeneratorMessage):
21+
# raise TypeError("request must be of type Message or _GeneratorMessage")
22+
23+
ack_rsponse = self.host.send_request_sync(self.target, self.request)
24+
25+
if ack_rsponse is None:
26+
raise RuntimeError("Failed to send request, no acknowledgment received.")
27+
28+
def __iter__(self):
29+
return self
30+
31+
def __next__(self):
32+
poll = _iris.get_iris().IOP.PrivateSession.Message.Poll._New()
33+
rsp = self.host.send_request_sync(self.target, poll)
34+
if rsp is None:
35+
raise StopIteration("No more responses available.")
36+
return rsp

src/iop/_message.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ class _PydanticPickleMessage(BaseModel):
2626
"""Base class for Pydantic-based messages that can be serialized to IRIS."""
2727

2828
def __init__(self, **data: Any):
29-
super().__init__(**data)
29+
super().__init__(**data)
30+
31+
class _GeneratorMessage(_Message):
32+
""""Base message to initialize generator function"""

0 commit comments

Comments
 (0)