Skip to content

Commit 2a14bc7

Browse files
committed
Make MapMutation a context manager
1 parent 24c575b commit 2a14bc7

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

immutables/_map.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3850,7 +3850,6 @@ mapmut_tp_richcompare(PyObject *v, PyObject *w, int op)
38503850
}
38513851
}
38523852

3853-
38543853
static PyObject *
38553854
mapmut_py_finalize(MapMutationObject *self, PyObject *args)
38563855
{
@@ -3868,6 +3867,24 @@ mapmut_py_finalize(MapMutationObject *self, PyObject *args)
38683867
return (PyObject *)o;
38693868
}
38703869

3870+
static PyObject *
3871+
mapmut_py_enter(MapMutationObject *self, PyObject *args)
3872+
{
3873+
Py_INCREF(self);
3874+
return (PyObject *)self;
3875+
}
3876+
3877+
static PyObject *
3878+
mapmut_py_exit(MapMutationObject *self, PyObject *args)
3879+
{
3880+
PyObject *ret = mapmut_py_finalize(self, NULL);
3881+
if (ret == NULL) {
3882+
return NULL;
3883+
}
3884+
Py_DECREF(ret);
3885+
Py_RETURN_FALSE;
3886+
}
3887+
38713888
static int
38723889
mapmut_tp_ass_sub(MapMutationObject *self, PyObject *key, PyObject *val)
38733890
{
@@ -3951,6 +3968,8 @@ static PyMethodDef MapMutation_methods[] = {
39513968
{"get", (PyCFunction)map_py_get, METH_VARARGS, NULL},
39523969
{"pop", (PyCFunction)mapmut_py_pop, METH_VARARGS, NULL},
39533970
{"finalize", (PyCFunction)mapmut_py_finalize, METH_NOARGS, NULL},
3971+
{"__enter__", (PyCFunction)mapmut_py_enter, METH_NOARGS, NULL},
3972+
{"__exit__", (PyCFunction)mapmut_py_exit, METH_VARARGS, NULL},
39543973
{NULL, NULL}
39553974
};
39563975

immutables/map.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,13 @@ def __init__(self, count, root):
633633
def set(self, key, val):
634634
self[key] = val
635635

636+
def __enter__(self):
637+
return self
638+
639+
def __exit__(self, *exc):
640+
self.finalize()
641+
return False
642+
636643
def __delitem__(self, key):
637644
if self.__mutid == 0:
638645
raise ValueError(f'mutation {self!r} has been finalized')

tests/test_map.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,27 @@ def test_map_mut_13(self):
11741174
with self.assertRaises(EqError):
11751175
mm.set(key2, 123)
11761176

1177+
def test_map_mut_14(self):
1178+
m = self.Map(a=1, b=2)
1179+
1180+
with m.mutate() as mm:
1181+
mm['z'] = 100
1182+
del mm['a']
1183+
1184+
self.assertEqual(mm.finalize(), self.Map(z=100, b=2))
1185+
1186+
def test_map_mut_15(self):
1187+
m = self.Map(a=1, b=2)
1188+
1189+
with self.assertRaises(ZeroDivisionError):
1190+
with m.mutate() as mm:
1191+
mm['z'] = 100
1192+
del mm['a']
1193+
1 / 0
1194+
1195+
self.assertEqual(mm.finalize(), self.Map(z=100, b=2))
1196+
self.assertEqual(m, self.Map(a=1, b=2))
1197+
11771198
def test_map_mut_stress(self):
11781199
COLLECTION_SIZE = 7000
11791200
TEST_ITERS_EVERY = 647

0 commit comments

Comments
 (0)