From 1e908af3354e20e18dfdcf30bc8aee6ab53ab1ee Mon Sep 17 00:00:00 2001
From: Georg Brandl <georg@python.org>
Date: Sat, 23 Oct 2010 17:31:52 +0000
Subject: #6518: enable context manager protocol for ossaudiodev types.

---
 Doc/library/ossaudiodev.rst  |  9 +++++++++
 Lib/test/test_ossaudiodev.py | 10 ++++++----
 Misc/NEWS                    |  2 ++
 Modules/ossaudiodev.c        | 25 +++++++++++++++++++++++++
 4 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst
index 3128b0a..3b5a7e4 100644
--- a/Doc/library/ossaudiodev.rst
+++ b/Doc/library/ossaudiodev.rst
@@ -159,6 +159,11 @@ and (read-only) attributes:
    is only useful in non-blocking mode.  Has no return value, since the amount of
    data written is always equal to the amount of data supplied.
 
+.. versionchanged:: 3.2
+   Audio device objects also support the context manager protocol, i.e. they can
+   be used in a :keyword:`with` statement.
+
+
 The following methods each map to exactly one :func:`ioctl` system call.  The
 correspondence is obvious: for example, :meth:`setfmt` corresponds to the
 ``SNDCTL_DSP_SETFMT`` ioctl, and :meth:`sync` to ``SNDCTL_DSP_SYNC`` (this can
@@ -346,6 +351,10 @@ The mixer object provides two file-like methods:
 
    Returns the file handle number of the open mixer device file.
 
+.. versionchanged:: 3.2
+   Mixer objects also support the context manager protocol.
+
+
 The remaining methods are specific to audio mixing:
 
 
diff --git a/Lib/test/test_ossaudiodev.py b/Lib/test/test_ossaudiodev.py
index 5dea640..9cb89d6 100644
--- a/Lib/test/test_ossaudiodev.py
+++ b/Lib/test/test_ossaudiodev.py
@@ -162,11 +162,13 @@ class OSSAudioDevTests(unittest.TestCase):
     def test_mixer_methods(self):
         # Issue #8139: ossaudiodev didn't initialize its types properly,
         # therefore some methods were unavailable.
-        mixer = ossaudiodev.openmixer()
-        try:
+        with ossaudiodev.openmixer() as mixer:
             self.assertGreaterEqual(mixer.fileno(), 0)
-        finally:
-            mixer.close()
+
+    def test_with(self):
+        with ossaudiodev.open('w') as dsp:
+            pass
+        self.assertTrue(dsp.closed)
 
 
 def test_main():
diff --git a/Misc/NEWS b/Misc/NEWS
index 71a4509..1f3a754 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -126,6 +126,8 @@ Library
 Extensions
 ----------
 
+- Issue #6518: Support context manager protcol for ossaudiodev types.
+
 - Issue #678250: Make mmap flush a noop on ACCESS_READ and ACCESS_COPY.
 
 - Issue #9054: Fix a crash occurring when using the pyexpat module
diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c
index 5c990ef..2c9d797 100644
--- a/Modules/ossaudiodev.c
+++ b/Modules/ossaudiodev.c
@@ -470,6 +470,23 @@ oss_close(oss_audio_t *self, PyObject *unused)
 }
 
 static PyObject *
+oss_self(PyObject *self)
+{
+    Py_INCREF(self);
+    return self;
+}
+
+static PyObject * 
+oss_exit(PyObject *self, PyObject *unused)
+{
+    PyObject *ret = PyObject_CallMethod(self, "close", NULL);
+    if (!ret)
+        return NULL;
+    Py_DECREF(ret);
+    Py_RETURN_NONE;
+}
+
+static PyObject *
 oss_fileno(oss_audio_t *self, PyObject *unused)
 {
     return PyLong_FromLong(self->fd);
@@ -782,6 +799,10 @@ static PyMethodDef oss_methods[] = {
     /* Aliases for backwards compatibility */
     { "flush",          (PyCFunction)oss_sync, METH_VARARGS },
 
+    /* Support for the context manager protocol */
+    { "__enter__",      oss_self, METH_NOARGS },
+    { "__exit__",       oss_exit, METH_VARARGS },
+
     { NULL,             NULL}           /* sentinel */
 };
 
@@ -790,6 +811,10 @@ static PyMethodDef oss_mixer_methods[] = {
     { "close",          (PyCFunction)oss_mixer_close, METH_NOARGS },
     { "fileno",         (PyCFunction)oss_mixer_fileno, METH_NOARGS },
 
+    /* Support for the context manager protocol */
+    { "__enter__",      oss_self, METH_NOARGS },
+    { "__exit__",       oss_exit, METH_VARARGS },
+
     /* Simple ioctl wrappers */
     { "controls",       (PyCFunction)oss_mixer_controls, METH_VARARGS },
     { "stereocontrols", (PyCFunction)oss_mixer_stereocontrols, METH_VARARGS},
-- 
cgit v0.12