langfun 0.1.2.dev202510300805__py3-none-any.whl → 0.1.2.dev202511010804__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.

@@ -17,8 +17,6 @@ import unittest
17
17
 
18
18
  from langfun.env import interface
19
19
  from langfun.env import test_utils
20
- from langfun.env.event_handlers import base as event_handler_base
21
-
22
20
 
23
21
  TestingEnvironment = test_utils.TestingEnvironment
24
22
  TestingSandbox = test_utils.TestingSandbox
@@ -26,453 +24,7 @@ TestingFeature = test_utils.TestingFeature
26
24
  TestingEventHandler = test_utils.TestingEventHandler
27
25
 
28
26
 
29
- class EnvironmentTests(unittest.TestCase):
30
-
31
- def test_basics(self):
32
- env = TestingEnvironment(
33
- image_ids=['test_image'],
34
- root_dir='/tmp',
35
- pool_size=0,
36
- features={'test_feature': TestingFeature()},
37
- outage_grace_period=1,
38
- outage_retry_interval=0,
39
- )
40
- self.assertIsNone(interface.Environment.current())
41
- self.assertEqual(env.image_ids, ['test_image'])
42
- self.assertFalse(env.supports_dynamic_image_loading)
43
- self.assertEqual(env.status, interface.Environment.Status.CREATED)
44
- self.assertFalse(env.is_online)
45
- self.assertEqual(env.min_pool_size('test_image'), 0)
46
- self.assertEqual(env.max_pool_size('test_image'), 0)
47
- self.assertEqual(env.sandbox_pool, {})
48
- self.assertEqual(env.id, interface.Environment.Id('testing-env'))
49
- self.assertEqual(env.outage_grace_period, 1)
50
- self.assertEqual(env.features['test_feature'].name, 'test_feature')
51
-
52
- self.assertIsNone(env.start_time)
53
-
54
- with env:
55
- self.assertEqual(env.status, interface.Environment.Status.ONLINE)
56
- self.assertIs(interface.Environment.current(), env)
57
- self.assertTrue(env.is_online)
58
- self.assertIsNotNone(env.start_time)
59
- self.assertEqual(env.offline_duration, 0.0)
60
- self.assertEqual(env.sandbox_pool, {})
61
- self.assertEqual(env.working_dir, '/tmp/testing-env')
62
-
63
- with env.sandbox(session_id='session1') as sb:
64
- self.assertEqual(
65
- sb.id, interface.Sandbox.Id(
66
- environment_id=env.id,
67
- image_id=sb.image_id,
68
- sandbox_id='0')
69
- )
70
- self.assertEqual(sb.session_id, 'session1')
71
- self.assertEqual(sb.working_dir, '/tmp/testing-env/test_image/0')
72
- self.assertTrue(sb.is_online)
73
- self.assertIs(sb.test_feature, sb.features['test_feature'])
74
- self.assertEqual(
75
- sb.test_feature.working_dir,
76
- '/tmp/testing-env/test_image/0/test_feature'
77
- )
78
- with self.assertRaises(AttributeError):
79
- _ = sb.test_feature2
80
- self.assertFalse(sb.is_online)
81
-
82
- with self.assertRaisesRegex(
83
- ValueError, 'Environment .* does not serve image ID .*'
84
- ):
85
- env.sandbox('test_image2')
86
-
87
- with env.test_feature() as feature:
88
- self.assertIsInstance(feature, TestingFeature)
89
- self.assertEqual(
90
- feature.sandbox.status, interface.Sandbox.Status.IN_SESSION
91
- )
92
- self.assertTrue(
93
- feature.sandbox.session_id.startswith('test_feature-session')
94
- )
95
-
96
- with self.assertRaises(AttributeError):
97
- _ = env.test_feature2
98
-
99
- def test_dynamic_image_loading(self):
100
- env = TestingEnvironment(
101
- image_ids=[],
102
- supports_dynamic_image_loading=True,
103
- pool_size=0,
104
- features={'test_feature': TestingFeature()},
105
- outage_grace_period=1,
106
- outage_retry_interval=0,
107
- )
108
- with env:
109
- with env.sandbox(image_id='test_image2') as sb:
110
- self.assertEqual(sb.image_id, 'test_image2')
111
-
112
- with self.assertRaisesRegex(
113
- ValueError, 'Environment .* does not have a default image ID.'
114
- ):
115
- env.sandbox()
116
-
117
- def test_dynamic_image_loading_with_pooling(self):
118
- env = TestingEnvironment(
119
- image_ids=[],
120
- supports_dynamic_image_loading=True,
121
- pool_size=2,
122
- features={'test_feature': TestingFeature()},
123
- outage_grace_period=1,
124
- outage_retry_interval=0,
125
- )
126
- with env:
127
- with env.sandbox(image_id='test_image'):
128
- self.assertEqual(len(env.sandbox_pool['test_image']), 1)
129
-
130
- with env.sandbox(image_id='test_image'):
131
- self.assertEqual(len(env.sandbox_pool['test_image']), 2)
132
-
133
- with self.assertRaises(interface.EnvironmentOverloadError):
134
- with env.sandbox(image_id='test_image'):
135
- pass
136
- self.assertEqual(len(env.sandbox_pool['test_image']), 2)
137
-
138
- with env.sandbox(image_id='test_image'):
139
- self.assertEqual(len(env.sandbox_pool['test_image']), 2)
140
-
141
- def test_image_feature_mappings(self):
142
- env = TestingEnvironment(
143
- image_ids=[
144
- 'test_image1',
145
- 'test_image2',
146
- ],
147
- features={
148
- 'test_feature': TestingFeature(
149
- applicable_images=['test_image1.*']
150
- ),
151
- 'test_feature2': TestingFeature(
152
- applicable_images=['test_image2.*']
153
- ),
154
- 'test_feature3': TestingFeature(
155
- applicable_images=['test_image.*']
156
- ),
157
- },
158
- pool_size=0,
159
- outage_grace_period=1,
160
- outage_retry_interval=0,
161
- sandbox_keepalive_interval=0,
162
- )
163
- with env:
164
- with env.sandbox(image_id='test_image1') as sb:
165
- self.assertIn('test_feature', sb.features)
166
- self.assertNotIn('test_feature2', sb.features)
167
- self.assertIn('test_feature3', sb.features)
168
-
169
- with env.sandbox(image_id='test_image2') as sb:
170
- self.assertNotIn('test_feature', sb.features)
171
- self.assertIn('test_feature2', sb.features)
172
- self.assertIn('test_feature3', sb.features)
173
-
174
- with env.test_feature() as feature:
175
- self.assertEqual(feature.sandbox.image_id, 'test_image1')
176
-
177
- with self.assertRaisesRegex(
178
- ValueError, 'Feature .* is not applicable to .*'
179
- ):
180
- with env.test_feature('test_image2'):
181
- pass
182
-
183
- with env.test_feature2() as feature:
184
- self.assertEqual(feature.sandbox.image_id, 'test_image2')
185
-
186
- with env.test_feature3() as feature:
187
- self.assertEqual(feature.sandbox.image_id, 'test_image1')
188
-
189
- with env.test_feature3('test_image2') as feature:
190
- self.assertEqual(feature.sandbox.image_id, 'test_image2')
191
-
192
- def test_feature_applicability_check(self):
193
- with self.assertRaisesRegex(
194
- ValueError, 'Feature .* is not applicable to .*'
195
- ):
196
- TestingEnvironment(
197
- image_ids=[
198
- 'test_image1',
199
- ],
200
- features={
201
- 'test_feature2': TestingFeature(
202
- applicable_images=['test_image2.*']
203
- ),
204
- },
205
- )
206
- env = TestingEnvironment(
207
- image_ids=[],
208
- supports_dynamic_image_loading=True,
209
- features={
210
- 'test_feature2': TestingFeature(
211
- applicable_images=['test_image2.*']
212
- ),
213
- },
214
- pool_size=0
215
- )
216
- with env:
217
- with self.assertRaisesRegex(
218
- ValueError, 'No image ID found for feature .*'
219
- ):
220
- with env.test_feature2():
221
- pass
222
-
223
- # Dynamically loaded IDs.
224
- with env.test_feature2('test_image2') as feature:
225
- self.assertEqual(feature.sandbox.image_id, 'test_image2')
226
-
227
- def test_pool_size(self):
228
- env = TestingEnvironment(
229
- image_ids=['test_image'],
230
- pool_size=1,
231
- outage_grace_period=1,
232
- outage_retry_interval=0,
233
- )
234
- self.assertEqual(env.min_pool_size('test_image'), 1)
235
- self.assertEqual(env.max_pool_size('test_image'), 1)
236
-
237
- env = TestingEnvironment(
238
- image_ids=['test_image'],
239
- pool_size=(0, 256),
240
- outage_grace_period=1,
241
- outage_retry_interval=0,
242
- )
243
- self.assertEqual(env.min_pool_size('test_image'), 0)
244
- self.assertEqual(env.max_pool_size('test_image'), 256)
245
-
246
- env = TestingEnvironment(
247
- image_ids=['test_image'],
248
- pool_size={
249
- 'test_.*': (0, 128),
250
- 'my.*': (5, 64),
251
- 'exact_image_name': 10,
252
- },
253
- outage_grace_period=1,
254
- outage_retry_interval=0,
255
- )
256
- self.assertEqual(env.min_pool_size('test_image'), 0)
257
- self.assertEqual(env.max_pool_size('test_image'), 128)
258
- self.assertEqual(env.min_pool_size('my_image'), 5)
259
- self.assertEqual(env.max_pool_size('my_image'), 64)
260
- self.assertEqual(env.min_pool_size('exact_image_name'), 10)
261
- self.assertEqual(env.max_pool_size('exact_image_name'), 10)
262
- self.assertEqual(env.min_pool_size('some_image'), 0) # default
263
- self.assertEqual(env.max_pool_size('some_image'), 256) # default
264
-
265
- def test_del(self):
266
- env = TestingEnvironment(
267
- features={'test_feature': TestingFeature()},
268
- pool_size=0,
269
- outage_grace_period=1,
270
- outage_retry_interval=0,
271
- sandbox_keepalive_interval=0,
272
- )
273
- env.start()
274
- sb = env.acquire()
275
- del sb
276
- del env
277
-
278
- def test_acquire_env_offline(self):
279
- env = TestingEnvironment(
280
- features={'test_feature': TestingFeature()},
281
- pool_size=0,
282
- outage_grace_period=1,
283
- outage_retry_interval=0,
284
- sandbox_keepalive_interval=0,
285
- )
286
- with self.assertRaises(interface.EnvironmentOutageError):
287
- env.acquire()
288
-
289
- def test_acquire_no_pooling(self):
290
- env = TestingEnvironment(
291
- features={'test_feature': TestingFeature()},
292
- pool_size=0,
293
- outage_grace_period=1,
294
- outage_retry_interval=0,
295
- sandbox_keepalive_interval=0,
296
- )
297
- with env:
298
- sb = env.acquire()
299
- self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
300
- self.assertIsNone(env.working_dir)
301
- self.assertIsNone(sb.working_dir)
302
- self.assertIsNone(sb.test_feature.working_dir)
303
-
304
- def test_acquire_no_pooling_with_error(self):
305
- env = TestingEnvironment(
306
- features={
307
- 'test_feature': TestingFeature(
308
- simulate_setup_error=interface.SandboxStateError
309
- )
310
- },
311
- pool_size=0,
312
- outage_grace_period=1,
313
- outage_retry_interval=0,
314
- sandbox_keepalive_interval=0,
315
- )
316
- with env:
317
- with self.assertRaises(interface.EnvironmentOutageError):
318
- env.acquire()
319
-
320
- def test_acquire_with_pooling(self):
321
- env = TestingEnvironment(
322
- features={'test_feature': TestingFeature()},
323
- pool_size=1,
324
- outage_grace_period=1,
325
- outage_retry_interval=0,
326
- sandbox_keepalive_interval=0,
327
- )
328
- with env:
329
- sb = env.acquire()
330
- self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
331
-
332
- def test_acquire_with_pooling_overload(self):
333
- env = TestingEnvironment(
334
- features={'test_feature': TestingFeature()},
335
- pool_size=1,
336
- outage_grace_period=1,
337
- outage_retry_interval=0,
338
- sandbox_keepalive_interval=0,
339
- )
340
- with env:
341
- sb = env.acquire()
342
- self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
343
- with self.assertRaises(interface.EnvironmentOverloadError):
344
- env.acquire()
345
-
346
- def test_acquire_with_growing_pool(self):
347
- env = TestingEnvironment(
348
- features={'test_feature': TestingFeature()},
349
- pool_size=(1, 3),
350
- outage_grace_period=1,
351
- outage_retry_interval=0,
352
- sandbox_keepalive_interval=0,
353
- )
354
- with env:
355
- self.assertEqual(len(env.sandbox_pool['test_image']), 1)
356
- self.assertEqual(
357
- env.stats(),
358
- {
359
- 'sandbox': {
360
- 'test_image': {
361
- 'created': 0,
362
- 'setting_up': 0,
363
- 'ready': 1,
364
- 'acquired': 0,
365
- 'in_session': 0,
366
- 'exiting_session': 0,
367
- 'shutting_down': 0,
368
- 'offline': 0,
369
- }
370
- }
371
- }
372
- )
373
- sb = env.acquire()
374
- self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
375
- self.assertEqual(
376
- env.stats(),
377
- {
378
- 'sandbox': {
379
- 'test_image': {
380
- 'created': 0,
381
- 'setting_up': 0,
382
- 'ready': 0,
383
- 'acquired': 1,
384
- 'in_session': 0,
385
- 'exiting_session': 0,
386
- 'shutting_down': 0,
387
- 'offline': 0,
388
- }
389
- }
390
- }
391
- )
392
- self.assertEqual(len(env.sandbox_pool['test_image']), 1)
393
- sb2 = env.acquire()
394
- self.assertEqual(sb2.status, interface.Sandbox.Status.ACQUIRED)
395
- self.assertEqual(len(env.sandbox_pool['test_image']), 2)
396
- self.assertEqual(
397
- env.stats(),
398
- {
399
- 'sandbox': {
400
- 'test_image': {
401
- 'created': 0,
402
- 'setting_up': 0,
403
- 'ready': 0,
404
- 'acquired': 2,
405
- 'in_session': 0,
406
- 'exiting_session': 0,
407
- 'shutting_down': 0,
408
- 'offline': 0,
409
- }
410
- }
411
- }
412
- )
413
- self.assertEqual(
414
- env.stats(),
415
- {
416
- 'sandbox': {}
417
- }
418
- )
419
-
420
- def test_acquire_with_growing_pool_failure(self):
421
- env = TestingEnvironment(
422
- features={'test_feature': TestingFeature()},
423
- pool_size=(1, 3),
424
- outage_grace_period=1,
425
- outage_retry_interval=0,
426
- sandbox_keepalive_interval=0,
427
- )
428
- with env:
429
- self.assertEqual(len(env.sandbox_pool), 1)
430
- sb = env.acquire()
431
- self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
432
-
433
- # Make future sandbox setup to fail.
434
- env.features.test_feature.rebind(
435
- simulate_setup_error=interface.SandboxStateError,
436
- skip_notification=True
437
- )
438
- with self.assertRaises(interface.EnvironmentOutageError):
439
- env.acquire()
440
-
441
- def test_housekeep_error(self):
442
- env = TestingEnvironment(
443
- features={'test_feature': TestingFeature()},
444
- pool_size=1,
445
- proactive_session_setup=True,
446
- outage_grace_period=1,
447
- outage_retry_interval=0,
448
- sandbox_keepalive_interval=0,
449
- )
450
- with env:
451
- self.assertEqual(len(env.sandbox_pool), 1)
452
- self.assertIn('test_image', env.sandbox_pool)
453
- self.assertEqual(
454
- env.sandbox_pool['test_image'][0].status,
455
- interface.Sandbox.Status.READY
456
- )
457
- # Make future sandbox setup to fail.
458
- env.features.test_feature.rebind(
459
- simulate_setup_error=interface.SandboxStateError,
460
- skip_notification=True
461
- )
462
- with self.assertRaises(interface.SandboxStateError):
463
- with env.sandbox() as sb:
464
- sb.shell('bad command', raise_error=interface.SandboxStateError)
465
- self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
466
- self.assertEqual(len(sb.state_errors), 1)
467
- sb_offline_time = time.time()
468
- while time.time() - sb_offline_time < 10:
469
- if not env.is_online:
470
- break
471
- time.sleep(0.5)
472
- self.assertFalse(env.is_online)
473
-
474
-
475
- class SandboxStatusTests(unittest.TestCase):
27
+ class BaseSandboxTests(unittest.TestCase):
476
28
 
477
29
  def setUp(self):
478
30
  super().setUp()
@@ -494,7 +46,7 @@ class SandboxStatusTests(unittest.TestCase):
494
46
  pool_size=pool_size,
495
47
  features=features,
496
48
  outage_grace_period=0,
497
- event_handlers=[self.event_handler],
49
+ event_handler=self.event_handler,
498
50
  outage_retry_interval=0,
499
51
  **kwargs
500
52
  )
@@ -604,19 +156,14 @@ class SandboxStatusTests(unittest.TestCase):
604
156
  ]
605
157
  )
606
158
 
607
- def test_practive_session_setup_with_setup_session_error(self):
159
+ def test_proactive_session_setup_with_setup_session_error(self):
608
160
  env = self._create_env(
609
161
  features={'test_feature': TestingFeature(setup_session_delay=0.5)},
610
162
  pool_size=1,
611
- )
612
- event_handler = TestingEventHandler(
613
- log_sandbox_status=True,
614
- log_feature_setup=True,
615
- log_session_setup=True,
163
+ housekeep_interval=10.0,
616
164
  )
617
165
  with env:
618
166
  with env.sandbox(session_id='session1') as sb:
619
- sb.add_event_handler(event_handler)
620
167
  sb.test_feature.rebind(
621
168
  simulate_setup_session_error=interface.SandboxStateError,
622
169
  skip_notification=True
@@ -630,15 +177,26 @@ class SandboxStatusTests(unittest.TestCase):
630
177
  self.assertEqual(len(sb.state_errors), 1)
631
178
  self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
632
179
  self.assertEqual(
633
- event_handler.logs,
180
+ self.event_handler.logs,
634
181
  [
635
182
  # pylint: disable=line-too-long
183
+ '[testing-env/test_image:0:0] shell: "test_feature" setup',
184
+ '[testing-env/test_image:0:0/test_feature] feature setup',
185
+ '[testing-env/test_image:0:0] shell: "test_feature" setup session',
186
+ '[testing-env/test_image:0:0/test_feature] feature setup session',
187
+ '[testing-env/test_image:0:0] created -> ready',
188
+ '[testing-env/test_image:0:0] sandbox started',
189
+ '[testing-env] environment started',
190
+ '[testing-env/test_image:0:0] ready -> acquired',
191
+ '[testing-env/test_image:0:0] acquired -> setting_up',
192
+ '[testing-env/test_image:0:0] setting_up -> in_session',
193
+ "[testing-env/test_image:0:0] session 'session1' started",
636
194
  '[testing-env/test_image:0:0] in_session -> exiting_session',
637
195
  '[testing-env/test_image:0:0/session1] shell: "test_feature" teardown session',
638
196
  '[testing-env/test_image:0:0/test_feature] feature teardown session',
639
197
  "[testing-env/test_image:0:0] session 'session1' ended",
640
198
  '[testing-env/test_image:0:0] exiting_session -> setting_up',
641
- '[testing-env/test_image:0:0/test_feature] feature setup session with SandboxStateError', # pylint: disable=line-too-long
199
+ '[testing-env/test_image:0:0/test_feature] feature setup session with SandboxStateError',
642
200
  '[testing-env/test_image:0:0] setting_up -> shutting_down',
643
201
  '[testing-env/test_image:0:0] shell: "test_feature" teardown',
644
202
  '[testing-env/test_image:0:0/test_feature] feature teardown',
@@ -1328,7 +886,7 @@ class SandboxActivityTests(unittest.TestCase):
1328
886
  outage_grace_period=0,
1329
887
  outage_retry_interval=0.1,
1330
888
  sandbox_keepalive_interval=0,
1331
- event_handlers=[event_handler],
889
+ event_handler=event_handler,
1332
890
  )
1333
891
  with env:
1334
892
  with env.sandbox(session_id='session1') as sb:
@@ -1374,27 +932,6 @@ class SandboxActivityTests(unittest.TestCase):
1374
932
  ]
1375
933
  )
1376
934
 
1377
- def test_remove_event_handler(self):
1378
- env = TestingEnvironment(
1379
- features={'test_feature': TestingFeature(housekeep_interval=0)},
1380
- pool_size=1,
1381
- outage_grace_period=0,
1382
- outage_retry_interval=0,
1383
- sandbox_keepalive_interval=0,
1384
- )
1385
- event_handler = TestingEventHandler()
1386
- with env:
1387
- with env.sandbox(session_id='session1') as sb:
1388
- sb.add_event_handler(event_handler)
1389
- sb.shell('test_feature')
1390
- sb.remove_event_handler(event_handler)
1391
- events = list(event_handler.logs)
1392
- sb.wait_until_not(interface.Sandbox.Status.SETTING_UP)
1393
- self.assertGreater(len(events), 0)
1394
- with env.sandbox(session_id='session2') as sb:
1395
- sb.shell('test_feature')
1396
- self.assertEqual(len(events), len(event_handler.logs))
1397
-
1398
935
 
1399
936
  class SandboxServiceTests(unittest.TestCase):
1400
937
 
@@ -1408,13 +945,13 @@ class SandboxServiceTests(unittest.TestCase):
1408
945
  outage_grace_period=0,
1409
946
  outage_retry_interval=0,
1410
947
  sandbox_keepalive_interval=0,
1411
- event_handlers=[self.event_handler],
948
+ event_handler=self.event_handler,
1412
949
  random_seed=1,
1413
950
  )
1414
951
 
1415
952
  def test_service_call_activity_log(self):
1416
953
 
1417
- class CustomEventHandler(event_handler_base.EventHandler):
954
+ class CustomEventHandler(interface.EventHandler):
1418
955
 
1419
956
  def __init__(self):
1420
957
  self.calls = []
@@ -1435,7 +972,7 @@ class SandboxServiceTests(unittest.TestCase):
1435
972
  env = TestingEnvironment(
1436
973
  features={'test_feature': TestingFeature()},
1437
974
  pool_size=0,
1438
- event_handlers=[event_handler],
975
+ event_handler=event_handler,
1439
976
  )
1440
977
  with env:
1441
978
  with env.test_feature(session_id='session1') as test_feature:
@@ -3,7 +3,7 @@
3
3
  # pylint: disable=g-importing-member
4
4
  # pylint: disable=g-bad-import-order
5
5
 
6
- from langfun.env.event_handlers.base import EventHandler
6
+ from langfun.env.event_handlers.chain import EventHandlerChain
7
7
 
8
8
  from langfun.env.event_handlers.event_logger import EventLogger
9
9
  from langfun.env.event_handlers.event_logger import ConsoleEventLogger