Skip to content

Commit 5087483

Browse files
committed
create modules to lazily import rather than relying on a random dependency
1 parent 29f934f commit 5087483

File tree

3 files changed

+71
-24
lines changed

3 files changed

+71
-24
lines changed

tests/worker/workflow_sandbox/test_runner.py

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import asyncio
44
import dataclasses
55
import functools
6-
import importlib
76
import inspect
87
import os
98
import sys
@@ -499,7 +498,7 @@ async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any:
499498
with workflow.unsafe.sandbox_import_policy(
500499
workflow.SandboxImportPolicy.WARN_ON_NON_PASSTHROUGH
501500
):
502-
import opentelemetry
501+
import tests.worker.workflow_sandbox.testmodules.lazy_module_interceptor
503502

504503
return await super().execute_workflow(input)
505504

@@ -516,17 +515,16 @@ class LazyImportWorkflow:
516515
@workflow.run
517516
async def run(self) -> None:
518517
try:
519-
import opentelemetry.version
518+
import tests.worker.workflow_sandbox.testmodules.lazy_module
520519
except DisallowedUnintentionalPassthroughError as err:
521520
raise ApplicationError(
522521
str(err), type="DisallowedUnintentionalPassthroughError"
523522
) from err
524523

525524

526-
async def test_workflow_sandbox_import_warnings(client: Client):
525+
async def test_workflow_sandbox_import_default_warnings(client: Client):
527526
restrictions = dataclasses.replace(
528527
SandboxRestrictions.default,
529-
import_policy=SandboxRestrictions.import_policy_all_warnings,
530528
# passthrough this test module to avoid a ton of noisy warnings
531529
passthrough_modules=SandboxRestrictions.passthrough_modules_default
532530
| {"tests.worker.workflow_sandbox.test_runner"},
@@ -536,30 +534,27 @@ async def test_workflow_sandbox_import_warnings(client: Client):
536534
client,
537535
task_queue=str(uuid.uuid4()),
538536
workflows=[LazyImportWorkflow],
539-
interceptors=[_TestInterceptor()],
540537
workflow_runner=SandboxedWorkflowRunner(restrictions),
541538
) as worker:
542-
with pytest.warns() as records:
539+
with pytest.warns() as recorder:
543540
await client.execute_workflow(
544541
LazyImportWorkflow.run,
545542
id=f"workflow-{uuid.uuid4()}",
546543
task_queue=worker.task_queue,
547544
)
548545

549-
expected_warnings = {
550-
"Module opentelemetry was not intentionally passed through to the sandbox.",
551-
"Module opentelemetry.version was imported after initial workflow load.",
552-
"Module opentelemetry.version was not intentionally passed through to the sandbox.",
553-
}
554-
actual_warnings = {str(w.message) for w in records}
555-
556-
assert expected_warnings <= actual_warnings
546+
_assert_expected_warnings(
547+
recorder,
548+
{
549+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module was imported after initial workflow load.",
550+
},
551+
)
557552

558553

559-
async def test_workflow_sandbox_import_errors(client: Client):
554+
async def test_workflow_sandbox_import_all_warnings(client: Client):
560555
restrictions = dataclasses.replace(
561556
SandboxRestrictions.default,
562-
import_policy=SandboxRestrictions.import_policy_disallow_unintentional_passthrough,
557+
import_policy=SandboxRestrictions.import_policy_all_warnings,
563558
# passthrough this test module to avoid a ton of noisy warnings
564559
passthrough_modules=SandboxRestrictions.passthrough_modules_default
565560
| {"tests.worker.workflow_sandbox.test_runner"},
@@ -569,18 +564,66 @@ async def test_workflow_sandbox_import_errors(client: Client):
569564
client,
570565
task_queue=str(uuid.uuid4()),
571566
workflows=[LazyImportWorkflow],
567+
interceptors=[_TestInterceptor()],
572568
workflow_runner=SandboxedWorkflowRunner(restrictions),
573569
) as worker:
574-
with pytest.raises(WorkflowFailureError) as err:
570+
with pytest.warns() as recorder:
575571
await client.execute_workflow(
576572
LazyImportWorkflow.run,
577573
id=f"workflow-{uuid.uuid4()}",
578574
task_queue=worker.task_queue,
579575
)
580576

581-
assert isinstance(err.value.cause, ApplicationError)
582-
assert err.value.cause.type == "DisallowedUnintentionalPassthroughError"
583-
assert (
584-
"Module opentelemetry.version was not intentionally passed through to the sandbox."
585-
== err.value.cause.message
586-
)
577+
_assert_expected_warnings(
578+
recorder,
579+
{
580+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module_interceptor was not intentionally passed through to the sandbox.",
581+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module was imported after initial workflow load.",
582+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module was not intentionally passed through to the sandbox.",
583+
},
584+
)
585+
586+
587+
async def test_workflow_sandbox_import_errors(client: Client):
588+
restrictions = dataclasses.replace(
589+
SandboxRestrictions.default,
590+
import_policy=SandboxRestrictions.import_policy_disallow_unintentional_passthrough,
591+
# passthrough this test module to avoid a ton of noisy warnings
592+
passthrough_modules=SandboxRestrictions.passthrough_modules_default
593+
| {"tests.worker.workflow_sandbox.test_runner"},
594+
)
595+
596+
async with Worker(
597+
client,
598+
task_queue=str(uuid.uuid4()),
599+
workflows=[LazyImportWorkflow],
600+
workflow_runner=SandboxedWorkflowRunner(restrictions),
601+
) as worker:
602+
with pytest.warns() as recorder:
603+
with pytest.raises(WorkflowFailureError) as err:
604+
await client.execute_workflow(
605+
LazyImportWorkflow.run,
606+
id=f"workflow-{uuid.uuid4()}",
607+
task_queue=worker.task_queue,
608+
)
609+
610+
assert isinstance(err.value.cause, ApplicationError)
611+
assert err.value.cause.type == "DisallowedUnintentionalPassthroughError"
612+
assert (
613+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module was not intentionally passed through to the sandbox."
614+
== err.value.cause.message
615+
)
616+
617+
_assert_expected_warnings(
618+
recorder,
619+
{
620+
"Module tests.worker.workflow_sandbox.testmodules.lazy_module was imported after initial workflow load.",
621+
},
622+
)
623+
624+
625+
def _assert_expected_warnings(
626+
recorder: pytest.WarningsRecorder, expected_warnings: Set[str]
627+
):
628+
actual_warnings = {str(w.message) for w in recorder}
629+
assert expected_warnings <= actual_warnings
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# intentionally empty
2+
# used during import warning tests
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# intentionally empty
2+
# used during import warning tests

0 commit comments

Comments
 (0)