|
27 | 27 | from apache_beam.internal import module_test
|
28 | 28 | from apache_beam.internal.cloudpickle_pickler import dumps
|
29 | 29 | from apache_beam.internal.cloudpickle_pickler import loads
|
| 30 | +from apache_beam.utils import shared |
| 31 | + |
| 32 | +GLOBAL_DICT_REF = module_test.GLOBAL_DICT |
| 33 | + |
| 34 | + |
| 35 | +# Allow weakref to dict |
| 36 | +class DictWrapper(dict): |
| 37 | + pass |
| 38 | + |
| 39 | + |
| 40 | +MAIN_MODULE_DICT = DictWrapper() |
| 41 | + |
| 42 | + |
| 43 | +def acquire_dict(): |
| 44 | + return DictWrapper() |
30 | 45 |
|
31 | 46 |
|
32 | 47 | class PicklerTest(unittest.TestCase):
|
33 | 48 |
|
34 | 49 | NO_MAPPINGPROXYTYPE = not hasattr(types, "MappingProxyType")
|
35 | 50 |
|
| 51 | + def test_module_global_pickled_by_value(self): |
| 52 | + self.assertIsNot( |
| 53 | + module_test.GLOBAL_DICT, loads(dumps(module_test.GLOBAL_DICT))) |
| 54 | + |
| 55 | + def test_main_shared_global_pickled_by_ref(self): |
| 56 | + shared_handler = shared.Shared() |
| 57 | + original_dict = shared_handler.acquire(acquire_dict) |
| 58 | + |
| 59 | + unpickled_dict = loads( |
| 60 | + dumps(lambda: shared_handler.acquire(acquire_dict)))() |
| 61 | + |
| 62 | + self.assertIs(original_dict, unpickled_dict) |
| 63 | + |
| 64 | + def test_function_defined_in_main_pickles_module_global_by_ref(self): |
| 65 | + def returns_global_dict(): |
| 66 | + return module_test.GLOBAL_DICT |
| 67 | + |
| 68 | + self.assertIs(module_test.GLOBAL_DICT, loads(dumps(returns_global_dict))()) |
| 69 | + |
| 70 | + def test_function_defined_in_main_pickles_module_global_ref_by_value(self): |
| 71 | + def returns_global_dict(): |
| 72 | + return GLOBAL_DICT_REF |
| 73 | + |
| 74 | + self.assertIsNot( |
| 75 | + module_test.GLOBAL_DICT, loads(dumps(returns_global_dict))()) |
| 76 | + |
| 77 | + def test_fn_contains_unpicklable_by_ref(self): |
| 78 | + self.assertEqual( |
| 79 | + module_test.UNPICLABLE_INSTANCE, |
| 80 | + loads(dumps(module_test.fn_returns_unpicklable))()) |
| 81 | + |
| 82 | + def test_imported_closure_contains_unpicklable_by_value_fails(self): |
| 83 | + # The entire closure is pickled by value, and therefore module_test is |
| 84 | + # not imported. Requires the module global to be pickled by value. |
| 85 | + with self.assertRaises(Exception): |
| 86 | + loads(dumps(module_test.closure_contains_unpicklable())) |
| 87 | + |
| 88 | + def test_imported_closure_contains_unpicklable_imports_self(self): |
| 89 | + # The closure imports module_test within the function definition |
| 90 | + # and returns self.UNPICLABLE_INSTANCE. This allows cloudpickle |
| 91 | + # to use submimort to reference module_test.UNPICLABLE_INSTANCE |
| 92 | + self.assertIs( |
| 93 | + module_test.UNPICLABLE_INSTANCE, |
| 94 | + loads(dumps(module_test.closure_contains_unpicklable_imports_self()))()) |
| 95 | + |
| 96 | + def test_main_closure_contains_imported_unpicklable_by_ref(self): |
| 97 | + def outer(): |
| 98 | + def inner(): |
| 99 | + return module_test.UNPICLABLE_INSTANCE |
| 100 | + |
| 101 | + return inner |
| 102 | + |
| 103 | + # Uses subimport to reference module_test.UNPICLABLE_INSTANCE rather than |
| 104 | + # recreate. |
| 105 | + loads(dumps(outer())) |
| 106 | + |
36 | 107 | def test_pickle_nested_enum_descriptor(self):
|
37 | 108 | NestedEnum = proto2_coder_test_messages_pb2.MessageD.NestedEnum
|
38 | 109 |
|
|
0 commit comments