@@ -346,7 +346,7 @@ def test_wrap_module():
346
346
347
347
348
348
def test_deprecate_attributes_assert_attributes_in_sys_modules ():
349
- subprocess_context (_test_deprecate_attributes_assert_attributes_in_sys_modules )( )
349
+ run_in_subprocess (_test_deprecate_attributes_assert_attributes_in_sys_modules )
350
350
351
351
352
352
def _test_deprecate_attributes_assert_attributes_in_sys_modules ():
@@ -635,42 +635,49 @@ def _type_repr_in_deprecated_module():
635
635
] + _deprecation_origin
636
636
637
637
638
- def _trace_unhandled_exceptions (* args , queue : 'multiprocessing.Queue' , func : Callable , ** kwargs ):
638
+ def _trace_unhandled_exceptions (* args , queue : 'multiprocessing.Queue' , func : Callable ):
639
639
try :
640
- func (* args , ** kwargs )
640
+ func (* args )
641
641
queue .put (None )
642
642
except BaseException as ex :
643
643
msg = str (ex )
644
644
queue .put ((type (ex ).__name__ , msg , traceback .format_exc ()))
645
645
646
646
647
- def subprocess_context (test_func ):
648
- """Ensures that sys.modules changes in subprocesses won't impact the parent process."""
647
+ def run_in_subprocess (test_func , * args ):
648
+ """Run a function in a subprocess.
649
+
650
+ This ensures that sys.modules changes in subprocesses won't impact the parent process.
651
+
652
+ Args:
653
+ test_func: The function to be run in a subprocess.
654
+ *args: Positional args to pass to the function.
655
+ """
656
+
649
657
assert callable (test_func ), (
650
- "subprocess_context expects a function. Did you call the function instead of passing "
658
+ "run_in_subprocess expects a function. Did you call the function instead of passing "
651
659
"it to this method?"
652
660
)
653
661
654
- ctx = multiprocessing . get_context ( ' spawn' if os . name == 'nt' else 'fork' )
655
-
656
- exception = ctx . Queue ( )
662
+ # Use spawn to ensure subprocesses are isolated.
663
+ # See https://github.com/quantumlib/Cirq/issues/6373
664
+ ctx = multiprocessing . get_context ( 'spawn' )
657
665
658
- def isolated_func (* args , ** kwargs ):
659
- kwargs ['queue' ] = exception
660
- kwargs ['func' ] = test_func
661
- p = ctx .Process (target = _trace_unhandled_exceptions , args = args , kwargs = kwargs )
662
- p .start ()
663
- p .join ()
664
- result = exception .get ()
665
- if result : # pragma: no cover
666
- ex_type , msg , ex_trace = result
667
- if ex_type == "Skipped" :
668
- warnings .warn (f"Skipping: { ex_type } : { msg } \n { ex_trace } " )
669
- pytest .skip (f'{ ex_type } : { msg } \n { ex_trace } ' )
670
- else :
671
- pytest .fail (f'{ ex_type } : { msg } \n { ex_trace } ' )
666
+ queue = ctx .Queue ()
672
667
673
- return isolated_func
668
+ p = ctx .Process (
669
+ target = _trace_unhandled_exceptions , args = args , kwargs = {'queue' : queue , 'func' : test_func }
670
+ )
671
+ p .start ()
672
+ p .join ()
673
+ result = queue .get ()
674
+ if result : # pragma: no cover
675
+ ex_type , msg , ex_trace = result
676
+ if ex_type == "Skipped" :
677
+ warnings .warn (f"Skipping: { ex_type } : { msg } \n { ex_trace } " )
678
+ pytest .skip (f'{ ex_type } : { msg } \n { ex_trace } ' )
679
+ else :
680
+ pytest .fail (f'{ ex_type } : { msg } \n { ex_trace } ' )
674
681
675
682
676
683
@mock .patch .dict (os .environ , {"CIRQ_FORCE_DEDUPE_MODULE_DEPRECATION" : "1" })
@@ -698,7 +705,7 @@ def isolated_func(*args, **kwargs):
698
705
],
699
706
)
700
707
def test_deprecated_module (outdated_method , deprecation_messages ):
701
- subprocess_context (_test_deprecated_module_inner )( outdated_method , deprecation_messages )
708
+ run_in_subprocess (_test_deprecated_module_inner , outdated_method , deprecation_messages )
702
709
703
710
704
711
def _test_deprecated_module_inner (outdated_method , deprecation_messages ):
@@ -736,7 +743,7 @@ def test_same_name_submodule_earlier_in_subtree():
736
743
cirq.ops.engine.calibration packages. The wrong resolution resulted in false circular
737
744
imports!
738
745
"""
739
- subprocess_context (_test_same_name_submodule_earlier_in_subtree_inner )( )
746
+ run_in_subprocess (_test_same_name_submodule_earlier_in_subtree_inner )
740
747
741
748
742
749
def _test_same_name_submodule_earlier_in_subtree_inner ():
@@ -748,7 +755,7 @@ def _test_same_name_submodule_earlier_in_subtree_inner():
748
755
def test_metadata_search_path ():
749
756
# to cater for metadata path finders
750
757
# https://docs.python.org/3/library/importlib.metadata.html#extending-the-search-algorithm
751
- subprocess_context (_test_metadata_search_path_inner )( )
758
+ run_in_subprocess (_test_metadata_search_path_inner )
752
759
753
760
754
761
def _test_metadata_search_path_inner (): # pragma: no cover
@@ -760,7 +767,7 @@ def _test_metadata_search_path_inner(): # pragma: no cover
760
767
761
768
762
769
def test_metadata_distributions_after_deprecated_submodule ():
763
- subprocess_context (_test_metadata_distributions_after_deprecated_submodule )( )
770
+ run_in_subprocess (_test_metadata_distributions_after_deprecated_submodule )
764
771
765
772
766
773
def _test_metadata_distributions_after_deprecated_submodule ():
@@ -779,7 +786,7 @@ def _test_metadata_distributions_after_deprecated_submodule():
779
786
780
787
781
788
def test_parent_spec_after_deprecated_submodule ():
782
- subprocess_context (_test_parent_spec_after_deprecated_submodule )( )
789
+ run_in_subprocess (_test_parent_spec_after_deprecated_submodule )
783
790
784
791
785
792
def _test_parent_spec_after_deprecated_submodule ():
@@ -791,7 +798,7 @@ def _test_parent_spec_after_deprecated_submodule():
791
798
def test_type_repr_in_new_module ():
792
799
# to cater for metadata path finders
793
800
# https://docs.python.org/3/library/importlib.metadata.html#extending-the-search-algorithm
794
- subprocess_context (_test_type_repr_in_new_module_inner )( )
801
+ run_in_subprocess (_test_type_repr_in_new_module_inner )
795
802
796
803
797
804
def _test_type_repr_in_new_module_inner ():
@@ -849,19 +856,19 @@ def _test_broken_module_3_inner():
849
856
850
857
851
858
def test_deprecated_module_error_handling_1 ():
852
- subprocess_context (_test_broken_module_1_inner )( )
859
+ run_in_subprocess (_test_broken_module_1_inner )
853
860
854
861
855
862
def test_deprecated_module_error_handling_2 ():
856
- subprocess_context (_test_broken_module_2_inner )( )
863
+ run_in_subprocess (_test_broken_module_2_inner )
857
864
858
865
859
866
def test_deprecated_module_error_handling_3 ():
860
- subprocess_context (_test_broken_module_3_inner )( )
867
+ run_in_subprocess (_test_broken_module_3_inner )
861
868
862
869
863
870
def test_new_module_is_top_level ():
864
- subprocess_context (_test_new_module_is_top_level_inner )( )
871
+ run_in_subprocess (_test_new_module_is_top_level_inner )
865
872
866
873
867
874
def _test_new_module_is_top_level_inner ():
@@ -877,7 +884,7 @@ def _test_new_module_is_top_level_inner():
877
884
878
885
879
886
def test_import_deprecated_with_no_attribute ():
880
- subprocess_context (_test_import_deprecated_with_no_attribute_inner )( )
887
+ run_in_subprocess (_test_import_deprecated_with_no_attribute_inner )
881
888
882
889
883
890
def _test_import_deprecated_with_no_attribute_inner ():
@@ -970,23 +977,23 @@ def module_repr(self, module: ModuleType) -> str:
970
977
971
978
def test_subprocess_test_failure ():
972
979
with pytest .raises (Failed , match = 'ValueError.*this fails' ):
973
- subprocess_context (_test_subprocess_test_failure_inner )( )
980
+ run_in_subprocess (_test_subprocess_test_failure_inner )
974
981
975
982
976
983
def _test_subprocess_test_failure_inner ():
977
984
raise ValueError ('this fails' )
978
985
979
986
980
987
def test_dir_is_still_valid ():
981
- subprocess_context (_dir_is_still_valid_inner )( )
988
+ run_in_subprocess (_dir_is_still_valid_inner )
982
989
983
990
984
991
def _dir_is_still_valid_inner ():
985
992
"""to ensure that create_attribute=True keeps the dir(module) intact"""
986
993
987
994
import cirq .testing ._compat_test_data as mod
988
995
989
- for m in ['fake_a' , 'info ' , 'module_a' , 'sys ' ]:
996
+ for m in ['fake_a' , 'logging ' , 'module_a' ]:
990
997
assert m in dir (mod )
991
998
992
999
0 commit comments