2020)
2121from hiero_sdk_python .logger .log_level import LogLevel
2222
23+
2324class MockServer :
2425 """Mock gRPC server that returns predetermined responses."""
25-
26+
2627 def __init__ (self , responses ):
2728 """
2829 Initialize a mock gRPC server with predetermined responses.
29-
30+
3031 Args:
3132 responses (list): List of response objects to return in sequence
3233 """
3334 self .responses = responses
3435 self .server = grpc .server (futures .ThreadPoolExecutor (max_workers = 10 ))
3536 self .port = _find_free_port ()
3637 self .address = f"localhost:{ self .port } "
37-
38+
3839 self ._register_services ()
39-
40+
4041 # Start the server
4142 self .server .add_insecure_port (self .address )
4243 self .server .start ()
43-
44+
4445 def _register_services (self ):
4546 """Register all necessary gRPC services."""
4647 # Create and register all servicers
4748 services = [
48- (crypto_service_pb2_grpc .CryptoServiceServicer ,
49- crypto_service_pb2_grpc .add_CryptoServiceServicer_to_server ),
50- (token_service_pb2_grpc .TokenServiceServicer ,
51- token_service_pb2_grpc .add_TokenServiceServicer_to_server ),
52- (consensus_service_pb2_grpc .ConsensusServiceServicer ,
53- consensus_service_pb2_grpc .add_ConsensusServiceServicer_to_server ),
54- (network_service_pb2_grpc .NetworkServiceServicer ,
55- network_service_pb2_grpc .add_NetworkServiceServicer_to_server ),
56- (file_service_pb2_grpc .FileServiceServicer ,
57- file_service_pb2_grpc .add_FileServiceServicer_to_server ),
58- (smart_contract_service_pb2_grpc .SmartContractServiceServicer ,
59- smart_contract_service_pb2_grpc .add_SmartContractServiceServicer_to_server ),
60- (schedule_service_pb2_grpc .ScheduleServiceServicer ,
61- schedule_service_pb2_grpc .add_ScheduleServiceServicer_to_server ),
62- (util_service_pb2_grpc .UtilServiceServicer ,
63- util_service_pb2_grpc .add_UtilServiceServicer_to_server ),
49+ (
50+ crypto_service_pb2_grpc .CryptoServiceServicer ,
51+ crypto_service_pb2_grpc .add_CryptoServiceServicer_to_server ,
52+ ),
53+ (
54+ token_service_pb2_grpc .TokenServiceServicer ,
55+ token_service_pb2_grpc .add_TokenServiceServicer_to_server ,
56+ ),
57+ (
58+ consensus_service_pb2_grpc .ConsensusServiceServicer ,
59+ consensus_service_pb2_grpc .add_ConsensusServiceServicer_to_server ,
60+ ),
61+ (
62+ network_service_pb2_grpc .NetworkServiceServicer ,
63+ network_service_pb2_grpc .add_NetworkServiceServicer_to_server ,
64+ ),
65+ (
66+ file_service_pb2_grpc .FileServiceServicer ,
67+ file_service_pb2_grpc .add_FileServiceServicer_to_server ,
68+ ),
69+ (
70+ smart_contract_service_pb2_grpc .SmartContractServiceServicer ,
71+ smart_contract_service_pb2_grpc .add_SmartContractServiceServicer_to_server ,
72+ ),
73+ (
74+ schedule_service_pb2_grpc .ScheduleServiceServicer ,
75+ schedule_service_pb2_grpc .add_ScheduleServiceServicer_to_server ,
76+ ),
77+ (
78+ util_service_pb2_grpc .UtilServiceServicer ,
79+ util_service_pb2_grpc .add_UtilServiceServicer_to_server ,
80+ ),
6481 ]
65-
82+
6683 for servicer_class , add_servicer_fn in services :
6784 servicer = self ._create_mock_servicer (servicer_class )
6885 add_servicer_fn (servicer , self .server )
69-
86+
7087 def _create_mock_servicer (self , servicer_class ):
7188 """
7289 Create a mock servicer that returns predetermined responses.
73-
90+
7491 Args:
7592 servicer_class: The gRPC servicer class to mock
76-
93+
7794 Returns:
7895 A mock servicer object
7996 """
8097 responses = self .responses
81-
98+
8299 class MockServicer (servicer_class ):
83100 def __getattribute__ (self , name ):
84101 # Get special attributes normally
85- if name in (' _next_response' , ' __class__' ):
102+ if name in (" _next_response" , " __class__" ):
86103 return super ().__getattribute__ (name )
87-
104+
88105 def method_wrapper (request , context ):
89106 nonlocal responses
90107 if not responses :
91108 # If no more responses are available, return None
92109 return None
93-
110+
94111 response = responses .pop (0 )
95-
112+
96113 if isinstance (response , RealRpcError ):
97114 # Abort with custom error
98115 context .abort (response .code (), response .details ())
99-
116+
100117 return response
101-
118+
102119 return method_wrapper
103-
120+
104121 return MockServicer ()
105-
122+
106123 def close (self ):
107124 """Stop the server."""
108125 self .server .stop (0 )
@@ -111,21 +128,21 @@ def close(self):
111128def _find_free_port ():
112129 """Find a free port on localhost."""
113130 with closing (socket .socket (socket .AF_INET , socket .SOCK_STREAM )) as s :
114- s .bind (('' , 0 ))
131+ s .bind (("" , 0 ))
115132 s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
116133 return s .getsockname ()[1 ]
117134
118135
119136class RealRpcError (grpc .RpcError ):
120137 """A more realistic gRPC error for testing."""
121-
138+
122139 def __init__ (self , status_code , details ):
123140 self ._status_code = status_code
124141 self ._details = details
125-
142+
126143 def code (self ):
127144 return self ._status_code
128-
145+
129146 def details (self ):
130147 return self ._details
131148
@@ -134,29 +151,28 @@ def details(self):
134151def mock_hedera_servers (response_sequences ):
135152 """
136153 Context manager that creates mock Hedera servers and a client.
137-
154+
138155 Args:
139156 response_sequences: List of response sequences, one for each mock server
140-
157+
141158 Yields:
142159 Client: The configured client
143160 """
144161 # Create mock servers
145162 servers = [MockServer (responses ) for responses in response_sequences ]
146-
163+
147164 try :
148165 # Configure the network with mock servers
149166 nodes = []
150167 for i , server in enumerate (servers ):
151168 node = _Node (AccountId (0 , 0 , 3 + i ), server .address , None )
152-
169+
153170 # force insecure transport
154171 node ._apply_transport_security (False )
155172 node ._set_verify_certificates (False )
156-
173+
157174 nodes .append (node )
158175
159-
160176 # Create network and client
161177 network = Network (nodes = nodes )
162178 client = Client (network )
@@ -165,7 +181,7 @@ def mock_hedera_servers(response_sequences):
165181 key = PrivateKey .generate ()
166182 client .set_operator (AccountId (0 , 0 , 1800 ), key )
167183 client .max_attempts = 4 # Configure for testing
168-
184+
169185 yield client
170186 finally :
171187 # Clean up the servers
0 commit comments