Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9abd394

Browse files
authored
Add some more cloudpickle tests. (#34683)
* Add tests. * Comments.
1 parent b7bd127 commit 9abd394

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

sdks/python/apache_beam/internal/cloudpickle_pickler_test.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,89 @@
2727
from apache_beam.internal import module_test
2828
from apache_beam.internal.cloudpickle_pickler import dumps
2929
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()
3045

3146

3247
class PicklerTest(unittest.TestCase):
3348

3449
NO_MAPPINGPROXYTYPE = not hasattr(types, "MappingProxyType")
3550

51+
def test_globals_main_are_pickled_by_value(self):
52+
self.assertIsNot(MAIN_MODULE_DICT, loads(dumps(lambda: MAIN_MODULE_DICT))())
53+
54+
def test_globals_shared_are_pickled_by_reference(self):
55+
shared_handler = shared.Shared()
56+
original_dict = shared_handler.acquire(acquire_dict)
57+
58+
unpickled_dict = loads(
59+
dumps(lambda: shared_handler.acquire(acquire_dict)))()
60+
61+
self.assertIs(original_dict, unpickled_dict)
62+
63+
def test_module_globals_are_pickled_by_value_when_directly_referenced(self):
64+
global_dict = loads(dumps(module_test.GLOBAL_DICT))
65+
66+
self.assertIsNot(module_test.GLOBAL_DICT, global_dict)
67+
68+
def test_function_main_with_explicit_module_reference_pickles_by_reference(
69+
self):
70+
def returns_global_dict():
71+
return module_test.GLOBAL_DICT
72+
73+
self.assertIs(module_test.GLOBAL_DICT, loads(dumps(returns_global_dict))())
74+
75+
def test_function_main_with_indirect_module_reference_pickles_by_value(self):
76+
def returns_global_dict():
77+
return GLOBAL_DICT_REF
78+
79+
self.assertIsNot(
80+
module_test.GLOBAL_DICT, loads(dumps(returns_global_dict))())
81+
82+
def test_function_referencing_unpicklable_object_works_when_imported(self):
83+
self.assertEqual(
84+
module_test.UNPICKLABLE_INSTANCE,
85+
loads(dumps(module_test.fn_returns_unpicklable))())
86+
87+
def test_closure_with_unpicklable_object_fails_when_imported(self):
88+
# The entire closure is pickled by value, and therefore module_test is
89+
# not imported. Requires the module global to be pickled by value.
90+
with self.assertRaises(Exception):
91+
loads(dumps(module_test.closure_contains_unpicklable()))
92+
93+
def test_closure_with_explicit_self_import_can_reference_unpicklable_objects(
94+
self):
95+
# The closure imports module_test within the function definition
96+
# and returns self.UNPICKLABLE_INSTANCE. This allows cloudpickle
97+
# to use submimort to reference module_test.UNPICKLABLE_INSTANCE
98+
self.assertIs(
99+
module_test.UNPICKLABLE_INSTANCE,
100+
loads(dumps(module_test.closure_contains_unpicklable_imports_self()))())
101+
102+
def test_closure_main_can_reference_unpicklable_module_objects(self):
103+
def outer():
104+
def inner():
105+
return module_test.UNPICKLABLE_INSTANCE
106+
107+
return inner
108+
109+
# Uses subimport to reference module_test.UNPICKLABLE_INSTANCE rather than
110+
# recreate.
111+
self.assertIs(module_test.UNPICKLABLE_INSTANCE, loads(dumps(outer()))())
112+
36113
def test_pickle_nested_enum_descriptor(self):
37114
NestedEnum = proto2_coder_test_messages_pb2.MessageD.NestedEnum
38115

sdks/python/apache_beam/internal/module_test.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,38 @@
2323
import sys
2424
from typing import Any
2525

26+
GLOBAL_DICT = {}
27+
28+
29+
class UnPicklable:
30+
def __init__(self, x):
31+
self.x = x
32+
33+
def __reduce__(self):
34+
return NotImplemented
35+
36+
37+
UNPICKLABLE_INSTANCE = UnPicklable(5)
38+
39+
40+
def closure_contains_unpicklable():
41+
def inner():
42+
return UNPICKLABLE_INSTANCE
43+
44+
return inner
45+
46+
47+
def closure_contains_unpicklable_imports_self():
48+
def inner():
49+
import apache_beam.internal.module_test as self_module
50+
return self_module.UNPICKLABLE_INSTANCE
51+
52+
return inner
53+
54+
55+
def fn_returns_unpicklable():
56+
return UNPICKLABLE_INSTANCE
57+
2658

2759
class TopClass(object):
2860
class NestedClass(object):

0 commit comments

Comments
 (0)