langfun 0.1.2.dev202509250804__py3-none-any.whl → 0.1.2.dev202509270803__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.
Potentially problematic release.
This version of langfun might be problematic. Click here for more details.
- langfun/core/llms/__init__.py +2 -0
- langfun/core/llms/openai.py +57 -0
- langfun/env/__init__.py +4 -5
- langfun/env/base_environment.py +41 -34
- langfun/env/base_feature.py +10 -1
- langfun/env/base_sandbox.py +27 -26
- langfun/env/base_test.py +106 -33
- langfun/env/event_handlers/__init__.py +12 -0
- langfun/env/event_handlers/base.py +271 -0
- langfun/env/event_handlers/event_logger.py +415 -0
- langfun/env/event_handlers/event_logger_test.py +289 -0
- langfun/env/interface.py +103 -380
- langfun/env/interface_test.py +3 -3
- langfun/env/load_balancers_test.py +3 -15
- langfun/env/test_utils.py +12 -26
- {langfun-0.1.2.dev202509250804.dist-info → langfun-0.1.2.dev202509270803.dist-info}/METADATA +1 -1
- {langfun-0.1.2.dev202509250804.dist-info → langfun-0.1.2.dev202509270803.dist-info}/RECORD +20 -16
- {langfun-0.1.2.dev202509250804.dist-info → langfun-0.1.2.dev202509270803.dist-info}/WHEEL +0 -0
- {langfun-0.1.2.dev202509250804.dist-info → langfun-0.1.2.dev202509270803.dist-info}/licenses/LICENSE +0 -0
- {langfun-0.1.2.dev202509250804.dist-info → langfun-0.1.2.dev202509270803.dist-info}/top_level.txt +0 -0
langfun/env/base_test.py
CHANGED
|
@@ -18,12 +18,13 @@ import unittest
|
|
|
18
18
|
from langfun.env import base_sandbox
|
|
19
19
|
from langfun.env import interface
|
|
20
20
|
from langfun.env import test_utils
|
|
21
|
+
from langfun.env.event_handlers import base as event_handler_base
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
TestingEnvironment = test_utils.TestingEnvironment
|
|
24
25
|
TestingSandbox = test_utils.TestingSandbox
|
|
25
26
|
TestingFeature = test_utils.TestingFeature
|
|
26
|
-
|
|
27
|
+
TestingEventHandler = test_utils.TestingEventHandler
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class EnvironmentTests(unittest.TestCase):
|
|
@@ -42,9 +43,8 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
42
43
|
self.assertEqual(env.min_pool_size, 0)
|
|
43
44
|
self.assertEqual(env.max_pool_size, 0)
|
|
44
45
|
self.assertEqual(env.sandbox_pool, [])
|
|
45
|
-
self.assertEqual(env.id, interface.
|
|
46
|
+
self.assertEqual(env.id, interface.Environment.Id('testing-env'))
|
|
46
47
|
self.assertEqual(env.outage_grace_period, 1)
|
|
47
|
-
self.assertEqual(env.stats_report_interval, 60)
|
|
48
48
|
self.assertEqual(env.features['test_feature'].name, 'test_feature')
|
|
49
49
|
|
|
50
50
|
self.assertIsNone(env.start_time)
|
|
@@ -60,12 +60,16 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
60
60
|
|
|
61
61
|
with env.sandbox('session1') as sb:
|
|
62
62
|
self.assertEqual(
|
|
63
|
-
sb.id, interface.
|
|
63
|
+
sb.id, interface.Sandbox.Id(environment_id=env.id, sandbox_id='0')
|
|
64
64
|
)
|
|
65
65
|
self.assertEqual(sb.session_id, 'session1')
|
|
66
66
|
self.assertEqual(sb.working_dir, '/tmp/testing-env/0')
|
|
67
67
|
self.assertTrue(sb.is_online)
|
|
68
68
|
self.assertIs(sb.test_feature, sb.features['test_feature'])
|
|
69
|
+
self.assertEqual(
|
|
70
|
+
sb.test_feature.working_dir,
|
|
71
|
+
'/tmp/testing-env/0/test_feature'
|
|
72
|
+
)
|
|
69
73
|
with self.assertRaises(AttributeError):
|
|
70
74
|
_ = sb.test_feature2
|
|
71
75
|
self.assertFalse(sb.is_online)
|
|
@@ -74,14 +78,26 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
74
78
|
with self.assertRaises(AttributeError):
|
|
75
79
|
_ = env.test_feature2
|
|
76
80
|
|
|
81
|
+
def test_del(self):
|
|
82
|
+
env = TestingEnvironment(
|
|
83
|
+
features={'test_feature': TestingFeature()},
|
|
84
|
+
pool_size=0,
|
|
85
|
+
outage_grace_period=1,
|
|
86
|
+
outage_retry_interval=0,
|
|
87
|
+
sandbox_keepalive_interval=0,
|
|
88
|
+
)
|
|
89
|
+
env.start()
|
|
90
|
+
sb = env.acquire()
|
|
91
|
+
del sb
|
|
92
|
+
del env
|
|
93
|
+
|
|
77
94
|
def test_acquire_env_offline(self):
|
|
78
95
|
env = TestingEnvironment(
|
|
79
96
|
features={'test_feature': TestingFeature()},
|
|
80
97
|
pool_size=0,
|
|
81
98
|
outage_grace_period=1,
|
|
82
99
|
outage_retry_interval=0,
|
|
83
|
-
|
|
84
|
-
stats_report_interval=1,
|
|
100
|
+
sandbox_keepalive_interval=0,
|
|
85
101
|
)
|
|
86
102
|
with self.assertRaises(interface.EnvironmentOutageError):
|
|
87
103
|
env.acquire()
|
|
@@ -92,12 +108,14 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
92
108
|
pool_size=0,
|
|
93
109
|
outage_grace_period=1,
|
|
94
110
|
outage_retry_interval=0,
|
|
95
|
-
|
|
96
|
-
stats_report_interval=1,
|
|
111
|
+
sandbox_keepalive_interval=0,
|
|
97
112
|
)
|
|
98
113
|
with env:
|
|
99
114
|
sb = env.acquire()
|
|
100
115
|
self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
|
|
116
|
+
self.assertIsNone(env.working_dir)
|
|
117
|
+
self.assertIsNone(sb.working_dir)
|
|
118
|
+
self.assertIsNone(sb.test_feature.working_dir)
|
|
101
119
|
|
|
102
120
|
def test_acquire_no_pooling_with_error(self):
|
|
103
121
|
env = TestingEnvironment(
|
|
@@ -109,8 +127,7 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
109
127
|
pool_size=0,
|
|
110
128
|
outage_grace_period=1,
|
|
111
129
|
outage_retry_interval=0,
|
|
112
|
-
|
|
113
|
-
stats_report_interval=1,
|
|
130
|
+
sandbox_keepalive_interval=0,
|
|
114
131
|
)
|
|
115
132
|
with env:
|
|
116
133
|
with self.assertRaises(interface.EnvironmentOutageError):
|
|
@@ -122,8 +139,7 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
122
139
|
pool_size=1,
|
|
123
140
|
outage_grace_period=1,
|
|
124
141
|
outage_retry_interval=0,
|
|
125
|
-
|
|
126
|
-
stats_report_interval=1,
|
|
142
|
+
sandbox_keepalive_interval=0,
|
|
127
143
|
)
|
|
128
144
|
with env:
|
|
129
145
|
sb = env.acquire()
|
|
@@ -135,8 +151,7 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
135
151
|
pool_size=1,
|
|
136
152
|
outage_grace_period=1,
|
|
137
153
|
outage_retry_interval=0,
|
|
138
|
-
|
|
139
|
-
stats_report_interval=1,
|
|
154
|
+
sandbox_keepalive_interval=0,
|
|
140
155
|
)
|
|
141
156
|
with env:
|
|
142
157
|
sb = env.acquire()
|
|
@@ -150,17 +165,76 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
150
165
|
pool_size=(1, 3),
|
|
151
166
|
outage_grace_period=1,
|
|
152
167
|
outage_retry_interval=0,
|
|
153
|
-
|
|
154
|
-
stats_report_interval=1,
|
|
168
|
+
sandbox_keepalive_interval=0,
|
|
155
169
|
)
|
|
156
170
|
with env:
|
|
157
171
|
self.assertEqual(len(env.sandbox_pool), 1)
|
|
172
|
+
self.assertEqual(
|
|
173
|
+
env.stats(),
|
|
174
|
+
{
|
|
175
|
+
'sandbox': {
|
|
176
|
+
'created': 0,
|
|
177
|
+
'setting_up': 0,
|
|
178
|
+
'ready': 1,
|
|
179
|
+
'acquired': 0,
|
|
180
|
+
'in_session': 0,
|
|
181
|
+
'exiting_session': 0,
|
|
182
|
+
'shutting_down': 0,
|
|
183
|
+
'offline': 0,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
)
|
|
158
187
|
sb = env.acquire()
|
|
159
188
|
self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
|
|
189
|
+
self.assertEqual(
|
|
190
|
+
env.stats(),
|
|
191
|
+
{
|
|
192
|
+
'sandbox': {
|
|
193
|
+
'created': 0,
|
|
194
|
+
'setting_up': 0,
|
|
195
|
+
'ready': 0,
|
|
196
|
+
'acquired': 1,
|
|
197
|
+
'in_session': 0,
|
|
198
|
+
'exiting_session': 0,
|
|
199
|
+
'shutting_down': 0,
|
|
200
|
+
'offline': 0,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
)
|
|
160
204
|
self.assertEqual(len(env.sandbox_pool), 1)
|
|
161
205
|
sb2 = env.acquire()
|
|
162
206
|
self.assertEqual(sb2.status, interface.Sandbox.Status.ACQUIRED)
|
|
163
207
|
self.assertEqual(len(env.sandbox_pool), 2)
|
|
208
|
+
self.assertEqual(
|
|
209
|
+
env.stats(),
|
|
210
|
+
{
|
|
211
|
+
'sandbox': {
|
|
212
|
+
'created': 0,
|
|
213
|
+
'setting_up': 0,
|
|
214
|
+
'ready': 0,
|
|
215
|
+
'acquired': 2,
|
|
216
|
+
'in_session': 0,
|
|
217
|
+
'exiting_session': 0,
|
|
218
|
+
'shutting_down': 0,
|
|
219
|
+
'offline': 0,
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
)
|
|
223
|
+
self.assertEqual(
|
|
224
|
+
env.stats(),
|
|
225
|
+
{
|
|
226
|
+
'sandbox': {
|
|
227
|
+
'created': 0,
|
|
228
|
+
'setting_up': 0,
|
|
229
|
+
'ready': 0,
|
|
230
|
+
'acquired': 0,
|
|
231
|
+
'in_session': 0,
|
|
232
|
+
'exiting_session': 0,
|
|
233
|
+
'shutting_down': 0,
|
|
234
|
+
'offline': 0,
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
)
|
|
164
238
|
|
|
165
239
|
def test_acquire_with_growing_pool_failure(self):
|
|
166
240
|
env = TestingEnvironment(
|
|
@@ -168,8 +242,7 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
168
242
|
pool_size=(1, 3),
|
|
169
243
|
outage_grace_period=1,
|
|
170
244
|
outage_retry_interval=0,
|
|
171
|
-
|
|
172
|
-
stats_report_interval=1,
|
|
245
|
+
sandbox_keepalive_interval=0,
|
|
173
246
|
)
|
|
174
247
|
with env:
|
|
175
248
|
self.assertEqual(len(env.sandbox_pool), 1)
|
|
@@ -184,15 +257,14 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
184
257
|
with self.assertRaises(interface.EnvironmentOutageError):
|
|
185
258
|
env.acquire()
|
|
186
259
|
|
|
187
|
-
def
|
|
260
|
+
def test_housekeep_error(self):
|
|
188
261
|
env = TestingEnvironment(
|
|
189
262
|
features={'test_feature': TestingFeature()},
|
|
190
263
|
pool_size=1,
|
|
191
264
|
proactive_session_setup=True,
|
|
192
265
|
outage_grace_period=1,
|
|
193
266
|
outage_retry_interval=0,
|
|
194
|
-
|
|
195
|
-
stats_report_interval=1,
|
|
267
|
+
sandbox_keepalive_interval=0,
|
|
196
268
|
)
|
|
197
269
|
with env:
|
|
198
270
|
self.assertEqual(len(env.sandbox_pool), 1)
|
|
@@ -216,7 +288,7 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
216
288
|
|
|
217
289
|
def setUp(self):
|
|
218
290
|
super().setUp()
|
|
219
|
-
self.event_handler =
|
|
291
|
+
self.event_handler = TestingEventHandler(
|
|
220
292
|
log_sandbox_status=True,
|
|
221
293
|
log_feature_setup=True,
|
|
222
294
|
log_session_setup=True,
|
|
@@ -246,6 +318,7 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
246
318
|
'feature2': TestingFeature(),
|
|
247
319
|
},
|
|
248
320
|
)
|
|
321
|
+
self.assertFalse(env.enable_pooling)
|
|
249
322
|
with env:
|
|
250
323
|
with env.sandbox('session1') as sb:
|
|
251
324
|
sb.shell('echo "hello"')
|
|
@@ -294,6 +367,7 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
294
367
|
pool_size=1,
|
|
295
368
|
proactive_session_setup=True,
|
|
296
369
|
)
|
|
370
|
+
self.assertTrue(env.enable_pooling)
|
|
297
371
|
with env:
|
|
298
372
|
with env.sandbox('session1') as sb:
|
|
299
373
|
sb.shell('echo "hello"')
|
|
@@ -343,7 +417,7 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
343
417
|
features={'test_feature': TestingFeature(setup_session_delay=0.5)},
|
|
344
418
|
pool_size=1,
|
|
345
419
|
)
|
|
346
|
-
event_handler =
|
|
420
|
+
event_handler = TestingEventHandler(
|
|
347
421
|
log_sandbox_status=True,
|
|
348
422
|
log_feature_setup=True,
|
|
349
423
|
log_session_setup=True,
|
|
@@ -919,6 +993,7 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
919
993
|
self.assertEqual(len(sb.state_errors), 0)
|
|
920
994
|
sb.shell('echo bar')
|
|
921
995
|
self.assertEqual(sb.status, interface.Sandbox.Status.IN_SESSION)
|
|
996
|
+
sb.wait_until_not(interface.Sandbox.Status.SETTING_UP)
|
|
922
997
|
self.assertEqual(sb.status, interface.Sandbox.Status.READY)
|
|
923
998
|
self.assertEqual(
|
|
924
999
|
self.event_handler.logs,
|
|
@@ -1020,7 +1095,7 @@ class SandboxActivityTests(unittest.TestCase):
|
|
|
1020
1095
|
env = TestingEnvironment(
|
|
1021
1096
|
features={'test_feature': TestingFeature(housekeep_interval=0)},
|
|
1022
1097
|
pool_size=1,
|
|
1023
|
-
|
|
1098
|
+
sandbox_keepalive_interval=0,
|
|
1024
1099
|
)
|
|
1025
1100
|
with env:
|
|
1026
1101
|
with env.sandbox('session1') as sb:
|
|
@@ -1037,7 +1112,7 @@ class SandboxActivityTests(unittest.TestCase):
|
|
|
1037
1112
|
pool_size=1,
|
|
1038
1113
|
outage_grace_period=0,
|
|
1039
1114
|
outage_retry_interval=0,
|
|
1040
|
-
|
|
1115
|
+
sandbox_keepalive_interval=0,
|
|
1041
1116
|
)
|
|
1042
1117
|
with env:
|
|
1043
1118
|
with env.sandbox('session1') as sb:
|
|
@@ -1052,7 +1127,7 @@ class SandboxActivityTests(unittest.TestCase):
|
|
|
1052
1127
|
while sb.housekeep_counter == housekeep_count or (
|
|
1053
1128
|
sb.status == interface.Sandbox.Status.IN_SESSION
|
|
1054
1129
|
):
|
|
1055
|
-
time.sleep(0.
|
|
1130
|
+
time.sleep(0.01)
|
|
1056
1131
|
self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
|
|
1057
1132
|
|
|
1058
1133
|
def test_remove_event_handler(self):
|
|
@@ -1061,10 +1136,9 @@ class SandboxActivityTests(unittest.TestCase):
|
|
|
1061
1136
|
pool_size=1,
|
|
1062
1137
|
outage_grace_period=0,
|
|
1063
1138
|
outage_retry_interval=0,
|
|
1064
|
-
|
|
1065
|
-
stats_report_interval=1,
|
|
1139
|
+
sandbox_keepalive_interval=0,
|
|
1066
1140
|
)
|
|
1067
|
-
event_handler =
|
|
1141
|
+
event_handler = TestingEventHandler()
|
|
1068
1142
|
with env:
|
|
1069
1143
|
with env.sandbox('session1') as sb:
|
|
1070
1144
|
sb.add_event_handler(event_handler)
|
|
@@ -1082,21 +1156,20 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1082
1156
|
def setUp(self):
|
|
1083
1157
|
super().setUp()
|
|
1084
1158
|
self.maxDiff = None
|
|
1085
|
-
self.event_handler =
|
|
1159
|
+
self.event_handler = TestingEventHandler()
|
|
1086
1160
|
self.env = TestingEnvironment(
|
|
1087
1161
|
features={'test_feature': TestingFeature()},
|
|
1088
1162
|
pool_size=0,
|
|
1089
1163
|
outage_grace_period=0,
|
|
1090
1164
|
outage_retry_interval=0,
|
|
1091
|
-
|
|
1165
|
+
sandbox_keepalive_interval=0,
|
|
1092
1166
|
event_handlers=[self.event_handler],
|
|
1093
|
-
stats_report_interval=1,
|
|
1094
1167
|
random_seed=1,
|
|
1095
1168
|
)
|
|
1096
1169
|
|
|
1097
1170
|
def test_service_call_activity_log(self):
|
|
1098
1171
|
|
|
1099
|
-
class CustomEventHandler(
|
|
1172
|
+
class CustomEventHandler(event_handler_base.EventHandler):
|
|
1100
1173
|
|
|
1101
1174
|
def __init__(self):
|
|
1102
1175
|
self.calls = []
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Environment event handlers."""
|
|
2
|
+
|
|
3
|
+
# pylint: disable=g-importing-member
|
|
4
|
+
# pylint: disable=g-bad-import-order
|
|
5
|
+
|
|
6
|
+
from langfun.env.event_handlers.base import EventHandler
|
|
7
|
+
|
|
8
|
+
from langfun.env.event_handlers.event_logger import EventLogger
|
|
9
|
+
from langfun.env.event_handlers.event_logger import ConsoleEventLogger
|
|
10
|
+
|
|
11
|
+
# pylint: enable=g-importing-member
|
|
12
|
+
# pylint: enable=g-bad-import-order
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
|
|
2
|
+
# Copyright 2025 The Langfun Authors
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Base classes for Langfun environment event handlers."""
|
|
16
|
+
|
|
17
|
+
from langfun.env import interface
|
|
18
|
+
|
|
19
|
+
Environment = interface.Environment
|
|
20
|
+
Sandbox = interface.Sandbox
|
|
21
|
+
Feature = interface.Feature
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class _SessionEventHandler:
|
|
25
|
+
"""Base class for session event handlers."""
|
|
26
|
+
|
|
27
|
+
def on_session_start(
|
|
28
|
+
self,
|
|
29
|
+
environment: Environment,
|
|
30
|
+
sandbox: Sandbox,
|
|
31
|
+
session_id: str,
|
|
32
|
+
duration: float,
|
|
33
|
+
error: BaseException | None
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Called when a sandbox session starts.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
environment: The environment.
|
|
39
|
+
sandbox: The sandbox.
|
|
40
|
+
session_id: The session ID.
|
|
41
|
+
duration: The time spent on starting the session.
|
|
42
|
+
error: The error that caused the session to start. If None, the session
|
|
43
|
+
started normally.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def on_session_end(
|
|
47
|
+
self,
|
|
48
|
+
environment: Environment,
|
|
49
|
+
sandbox: Sandbox,
|
|
50
|
+
session_id: str,
|
|
51
|
+
lifetime: float,
|
|
52
|
+
error: BaseException | None
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Called when a sandbox session ends.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
environment: The environment.
|
|
58
|
+
sandbox: The sandbox.
|
|
59
|
+
session_id: The session ID.
|
|
60
|
+
lifetime: The session lifetime in seconds.
|
|
61
|
+
error: The error that caused the session to end. If None, the session
|
|
62
|
+
ended normally.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class _FeatureEventHandler:
|
|
67
|
+
"""Base class for feature event handlers."""
|
|
68
|
+
|
|
69
|
+
def on_feature_setup(
|
|
70
|
+
self,
|
|
71
|
+
environment: Environment,
|
|
72
|
+
sandbox: Sandbox,
|
|
73
|
+
feature: Feature,
|
|
74
|
+
duration: float,
|
|
75
|
+
error: BaseException | None
|
|
76
|
+
) -> None:
|
|
77
|
+
"""Called when a sandbox feature is setup."""
|
|
78
|
+
|
|
79
|
+
def on_feature_teardown(
|
|
80
|
+
self,
|
|
81
|
+
environment: Environment,
|
|
82
|
+
sandbox: Sandbox,
|
|
83
|
+
feature: Feature,
|
|
84
|
+
duration: float,
|
|
85
|
+
error: BaseException | None
|
|
86
|
+
) -> None:
|
|
87
|
+
"""Called when a sandbox feature is teardown."""
|
|
88
|
+
|
|
89
|
+
def on_feature_teardown_session(
|
|
90
|
+
self,
|
|
91
|
+
environment: Environment,
|
|
92
|
+
sandbox: Sandbox,
|
|
93
|
+
feature: Feature,
|
|
94
|
+
session_id: str,
|
|
95
|
+
duration: float,
|
|
96
|
+
error: BaseException | None
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Called when a feature is teardown with a session."""
|
|
99
|
+
|
|
100
|
+
def on_feature_setup_session(
|
|
101
|
+
self,
|
|
102
|
+
environment: Environment,
|
|
103
|
+
sandbox: Sandbox,
|
|
104
|
+
feature: Feature,
|
|
105
|
+
session_id: str | None,
|
|
106
|
+
duration: float,
|
|
107
|
+
error: BaseException | None
|
|
108
|
+
) -> None:
|
|
109
|
+
"""Called when a feature is setup with a session."""
|
|
110
|
+
|
|
111
|
+
def on_feature_housekeep(
|
|
112
|
+
self,
|
|
113
|
+
environment: Environment,
|
|
114
|
+
sandbox: Sandbox,
|
|
115
|
+
feature: Feature,
|
|
116
|
+
counter: int,
|
|
117
|
+
duration: float,
|
|
118
|
+
error: BaseException | None
|
|
119
|
+
) -> None:
|
|
120
|
+
"""Called when a sandbox feature is housekeeping."""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class _SandboxEventHandler(_FeatureEventHandler, _SessionEventHandler):
|
|
124
|
+
"""Base class for sandbox event handlers."""
|
|
125
|
+
|
|
126
|
+
def on_sandbox_start(
|
|
127
|
+
self,
|
|
128
|
+
environment: Environment,
|
|
129
|
+
sandbox: Sandbox,
|
|
130
|
+
duration: float,
|
|
131
|
+
error: BaseException | None
|
|
132
|
+
) -> None:
|
|
133
|
+
"""Called when a sandbox is started.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
environment: The environment.
|
|
137
|
+
sandbox: The sandbox.
|
|
138
|
+
duration: The time spent on starting the sandbox.
|
|
139
|
+
error: The error that caused the sandbox to start. If None, the sandbox
|
|
140
|
+
started normally.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
def on_sandbox_status_change(
|
|
144
|
+
self,
|
|
145
|
+
environment: Environment,
|
|
146
|
+
sandbox: Sandbox,
|
|
147
|
+
old_status: 'Sandbox.Status',
|
|
148
|
+
new_status: 'Sandbox.Status',
|
|
149
|
+
span: float,
|
|
150
|
+
) -> None:
|
|
151
|
+
"""Called when a sandbox status changes.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
environment: The environment.
|
|
155
|
+
sandbox: The sandbox.
|
|
156
|
+
old_status: The old sandbox status.
|
|
157
|
+
new_status: The new sandbox status.
|
|
158
|
+
span: Time spent on the old status in seconds.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
def on_sandbox_shutdown(
|
|
162
|
+
self,
|
|
163
|
+
environment: Environment,
|
|
164
|
+
sandbox: Sandbox,
|
|
165
|
+
lifetime: float,
|
|
166
|
+
error: BaseException | None
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Called when a sandbox is shutdown.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
environment: The environment.
|
|
172
|
+
sandbox: The sandbox.
|
|
173
|
+
lifetime: The sandbox lifetime in seconds.
|
|
174
|
+
error: The error that caused the sandbox to shutdown. If None, the
|
|
175
|
+
sandbox shutdown normally.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def on_sandbox_activity(
|
|
179
|
+
self,
|
|
180
|
+
name: str,
|
|
181
|
+
environment: Environment,
|
|
182
|
+
sandbox: Sandbox,
|
|
183
|
+
feature: Feature | None,
|
|
184
|
+
session_id: str | None,
|
|
185
|
+
duration: float,
|
|
186
|
+
error: BaseException | None,
|
|
187
|
+
**kwargs
|
|
188
|
+
) -> None:
|
|
189
|
+
"""Called when a sandbox activity is performed.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
name: The name of the sandbox activity.
|
|
193
|
+
environment: The environment.
|
|
194
|
+
sandbox: The sandbox.
|
|
195
|
+
feature: The feature that is associated with the sandbox activity.
|
|
196
|
+
session_id: The session ID.
|
|
197
|
+
duration: The sandbox activity duration in seconds.
|
|
198
|
+
error: The error that caused the sandbox activity to perform. If None,
|
|
199
|
+
the sandbox activity performed normally.
|
|
200
|
+
**kwargs: The keyword arguments of the sandbox activity.
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
def on_sandbox_housekeep(
|
|
204
|
+
self,
|
|
205
|
+
environment: Environment,
|
|
206
|
+
sandbox: Sandbox,
|
|
207
|
+
counter: int,
|
|
208
|
+
duration: float,
|
|
209
|
+
error: BaseException | None
|
|
210
|
+
) -> None:
|
|
211
|
+
"""Called when a sandbox finishes a round of housekeeping.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
environment: The environment.
|
|
215
|
+
sandbox: The sandbox.
|
|
216
|
+
counter: Zero-based counter of the housekeeping round.
|
|
217
|
+
duration: The sandbox housekeeping duration in seconds.
|
|
218
|
+
error: The error that caused the sandbox to housekeeping. If None, the
|
|
219
|
+
sandbox housekeeping normally.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class EventHandler(_SandboxEventHandler):
|
|
224
|
+
"""Base class for event handlers of an environment."""
|
|
225
|
+
|
|
226
|
+
def on_environment_start(
|
|
227
|
+
self,
|
|
228
|
+
environment: Environment,
|
|
229
|
+
duration: float,
|
|
230
|
+
error: BaseException | None
|
|
231
|
+
) -> None:
|
|
232
|
+
"""Called when the environment is started.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
environment: The environment.
|
|
236
|
+
duration: The environment start duration in seconds.
|
|
237
|
+
error: The error that failed the environment start. If None, the
|
|
238
|
+
environment started normally.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def on_environment_housekeep(
|
|
242
|
+
self,
|
|
243
|
+
environment: Environment,
|
|
244
|
+
counter: int,
|
|
245
|
+
duration: float,
|
|
246
|
+
error: BaseException | None
|
|
247
|
+
) -> None:
|
|
248
|
+
"""Called when the environment finishes a round of housekeeping.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
environment: The environment.
|
|
252
|
+
counter: Zero-based counter of the housekeeping round.
|
|
253
|
+
duration: The environment start duration in seconds.
|
|
254
|
+
error: The error that failed the housekeeping. If None, the
|
|
255
|
+
housekeeping succeeded.
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
def on_environment_shutdown(
|
|
259
|
+
self,
|
|
260
|
+
environment: Environment,
|
|
261
|
+
lifetime: float,
|
|
262
|
+
error: BaseException | None
|
|
263
|
+
) -> None:
|
|
264
|
+
"""Called when the environment is shutdown.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
environment: The environment.
|
|
268
|
+
lifetime: The environment lifetime in seconds.
|
|
269
|
+
error: The error that caused the environment to shutdown. If None, the
|
|
270
|
+
environment shutdown normally.
|
|
271
|
+
"""
|