proxies.
A manager returned by :func:`Manager` will support types
- :class:`list`, :class:`dict`, :class:`~managers.Namespace`, :class:`Lock`,
+ :class:`list`, :class:`dict`, :class:`set`, :class:`~managers.Namespace`, :class:`Lock`,
:class:`RLock`, :class:`Semaphore`, :class:`BoundedSemaphore`,
:class:`Condition`, :class:`Event`, :class:`Barrier`,
:class:`Queue`, :class:`Value` and :class:`Array`. For example, ::
from multiprocessing import Process, Manager
- def f(d, l):
+ def f(d, l, s):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.reverse()
+ s.add('a')
+ s.add('b')
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list(range(10))
+ s = manager.set()
- p = Process(target=f, args=(d, l))
+ p = Process(target=f, args=(d, l, s))
p.start()
p.join()
print(d)
print(l)
+ print(s)
will print ::
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+ {'a', 'b'}
Server process managers are more flexible than using shared memory objects
because they can be made to support arbitrary object types. Also, a single
Create a shared :class:`list` object and return a proxy for it.
+ .. method:: set()
+ set(sequence)
+ set(mapping)
+
+ Create a shared :class:`set` object and return a proxy for it.
+
+ .. versionadded:: next
+ :class:`set` support was added.
+
.. versionchanged:: 3.6
Shared objects are capable of being nested. For example, a shared
container object such as a shared list can contain other shared objects
collections.abc.MutableMapping.register(_BaseDictProxy)
+_BaseSetProxy = MakeProxyType("_BaseSetProxy", (
+ '__and__', '__class_getitem__', '__contains__', '__iand__', '__ior__',
+ '__isub__', '__iter__', '__ixor__', '__len__', '__or__', '__rand__',
+ '__ror__', '__rsub__', '__rxor__', '__sub__', '__xor__',
+ '__ge__', '__gt__', '__le__', '__lt__',
+ 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard',
+ 'intersection', 'intersection_update', 'isdisjoint', 'issubset',
+ 'issuperset', 'pop', 'remove', 'symmetric_difference',
+ 'symmetric_difference_update', 'union', 'update',
+))
+
+class SetProxy(_BaseSetProxy):
+ def __ior__(self, value):
+ self._callmethod('__ior__', (value,))
+ return self
+ def __iand__(self, value):
+ self._callmethod('__iand__', (value,))
+ return self
+ def __ixor__(self, value):
+ self._callmethod('__ixor__', (value,))
+ return self
+ def __isub__(self, value):
+ self._callmethod('__isub__', (value,))
+ return self
+
+ __class_getitem__ = classmethod(types.GenericAlias)
+
+collections.abc.MutableMapping.register(_BaseSetProxy)
+
+
ArrayProxy = MakeProxyType('ArrayProxy', (
'__len__', '__getitem__', '__setitem__'
))
SyncManager.register('Pool', pool.Pool, PoolProxy)
SyncManager.register('list', list, ListProxy)
SyncManager.register('dict', dict, DictProxy)
+SyncManager.register('set', set, SetProxy)
SyncManager.register('Value', Value, ValueProxy)
SyncManager.register('Array', Array, ArrayProxy)
SyncManager.register('Namespace', Namespace, NamespaceProxy)
o.y = 1
self.run_worker(self._test_namespace, o)
+ @classmethod
+ def _test_set_operator_symbols(cls, obj):
+ case = unittest.TestCase()
+ obj.update(['a', 'b', 'c'])
+ case.assertEqual(len(obj), 3)
+ case.assertIn('a', obj)
+ case.assertNotIn('d', obj)
+ result = obj | {'d', 'e'}
+ case.assertSetEqual(result, {'a', 'b', 'c', 'd', 'e'})
+ result = {'d', 'e'} | obj
+ case.assertSetEqual(result, {'a', 'b', 'c', 'd', 'e'})
+ obj |= {'d', 'e'}
+ case.assertSetEqual(obj, {'a', 'b', 'c', 'd', 'e'})
+ case.assertIsInstance(obj, multiprocessing.managers.SetProxy)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = {'a', 'b', 'd'} - obj
+ case.assertSetEqual(result, {'d'})
+ result = obj - {'a', 'b'}
+ case.assertSetEqual(result, {'c'})
+ obj -= {'a', 'b'}
+ case.assertSetEqual(obj, {'c'})
+ case.assertIsInstance(obj, multiprocessing.managers.SetProxy)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = {'b', 'c', 'd'} ^ obj
+ case.assertSetEqual(result, {'a', 'd'})
+ result = obj ^ {'b', 'c', 'd'}
+ case.assertSetEqual(result, {'a', 'd'})
+ obj ^= {'b', 'c', 'd'}
+ case.assertSetEqual(obj, {'a', 'd'})
+ case.assertIsInstance(obj, multiprocessing.managers.SetProxy)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = obj & {'b', 'c', 'd'}
+ case.assertSetEqual(result, {'b', 'c'})
+ result = {'b', 'c', 'd'} & obj
+ case.assertSetEqual(result, {'b', 'c'})
+ obj &= {'b', 'c', 'd'}
+ case.assertSetEqual(obj, {'b', 'c'})
+ case.assertIsInstance(obj, multiprocessing.managers.SetProxy)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ case.assertSetEqual(set(obj), {'a', 'b', 'c'})
+
+ @classmethod
+ def _test_set_operator_methods(cls, obj):
+ case = unittest.TestCase()
+ obj.add('d')
+ case.assertIn('d', obj)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ copy_obj = obj.copy()
+ case.assertSetEqual(copy_obj, obj)
+ obj.remove('a')
+ case.assertNotIn('a', obj)
+ case.assertRaises(KeyError, obj.remove, 'a')
+
+ obj.clear()
+ obj.update(['a'])
+ obj.discard('a')
+ case.assertNotIn('a', obj)
+ obj.discard('a')
+ case.assertNotIn('a', obj)
+ obj.update(['a'])
+ popped = obj.pop()
+ case.assertNotIn(popped, obj)
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = obj.intersection({'b', 'c', 'd'})
+ case.assertSetEqual(result, {'b', 'c'})
+ obj.intersection_update({'b', 'c', 'd'})
+ case.assertSetEqual(obj, {'b', 'c'})
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = obj.difference({'a', 'b'})
+ case.assertSetEqual(result, {'c'})
+ obj.difference_update({'a', 'b'})
+ case.assertSetEqual(obj, {'c'})
+
+ obj.clear()
+ obj.update(['a', 'b', 'c'])
+ result = obj.symmetric_difference({'b', 'c', 'd'})
+ case.assertSetEqual(result, {'a', 'd'})
+ obj.symmetric_difference_update({'b', 'c', 'd'})
+ case.assertSetEqual(obj, {'a', 'd'})
+
+ @classmethod
+ def _test_set_comparisons(cls, obj):
+ case = unittest.TestCase()
+ obj.update(['a', 'b', 'c'])
+ result = obj.union({'d', 'e'})
+ case.assertSetEqual(result, {'a', 'b', 'c', 'd', 'e'})
+ case.assertTrue(obj.isdisjoint({'d', 'e'}))
+ case.assertFalse(obj.isdisjoint({'a', 'd'}))
+
+ case.assertTrue(obj.issubset({'a', 'b', 'c', 'd'}))
+ case.assertFalse(obj.issubset({'a', 'b'}))
+ case.assertLess(obj, {'a', 'b', 'c', 'd'})
+ case.assertLessEqual(obj, {'a', 'b', 'c'})
+
+ case.assertTrue(obj.issuperset({'a', 'b'}))
+ case.assertFalse(obj.issuperset({'a', 'b', 'd'}))
+ case.assertGreater(obj, {'a'})
+ case.assertGreaterEqual(obj, {'a', 'b'})
+
+ def test_set(self):
+ o = self.manager.set()
+ self.run_worker(self._test_set_operator_symbols, o)
+ o = self.manager.set()
+ self.run_worker(self._test_set_operator_methods, o)
+ o = self.manager.set()
+ self.run_worker(self._test_set_comparisons, o)
+
+ def test_set_init(self):
+ o = self.manager.set({'a', 'b', 'c'})
+ self.assertSetEqual(o, {'a', 'b', 'c'})
+ o = self.manager.set(["a", "b", "c"])
+ self.assertSetEqual(o, {"a", "b", "c"})
+ o = self.manager.set({"a": 1, "b": 2, "c": 3})
+ self.assertSetEqual(o, {"a", "b", "c"})
+ self.assertRaises(RemoteError, self.manager.set, 1234)
+
+ def test_set_contain_all_method(self):
+ o = self.manager.set()
+ set_methods = {
+ '__and__', '__class_getitem__', '__contains__', '__iand__', '__ior__',
+ '__isub__', '__iter__', '__ixor__', '__len__', '__or__', '__rand__',
+ '__ror__', '__rsub__', '__rxor__', '__sub__', '__xor__',
+ '__ge__', '__gt__', '__le__', '__lt__',
+ 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard',
+ 'intersection', 'intersection_update', 'isdisjoint', 'issubset',
+ 'issuperset', 'pop', 'remove', 'symmetric_difference',
+ 'symmetric_difference_update', 'union', 'update',
+ }
+ self.assertLessEqual(set_methods, set(dir(o)))
+
class TestNamedResource(unittest.TestCase):
@only_run_in_spawn_testsuite("spawn specific test.")