We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
atomic write umask
Reported on gitter.im/ipython/ipython by @bigzachattack 

Sadly no one was on the chat at that time, too busy with a big bearded men 
dressed in red trying to smuggle things in our houses through the cheminee. 

```
I noticed today working in master, that any new notebook I create or copy has permissions
0o600 and ignores my umask. In IPython.utils.io.atomic_writing() uses mkstemp() to create
a temporary file for the atomic write. According to the python docs, mkstemp creates
files as 0o600.

After the write succeeds to the tmp file, _copy_metadata is called to copy the metadata
from the original file to destination file. It will throw an exception if there is no
source file. Thus when the notebook is copied into the notebook dir, it has
permissions 0o600.

Is this desired behavior, temporary, or a bug? I work in an environment where are default
permissions are 0o660 to allow for users to easily share information, so defaulting new
notebooks to 0o600 seriously inhibits this ability.
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `IPython/utils/io.py`
Content:
```
1 # encoding: utf-8
2 """
3 IO related utilities.
4 """
5 
6 #-----------------------------------------------------------------------------
7 #  Copyright (C) 2008-2011  The IPython Development Team
8 #
9 #  Distributed under the terms of the BSD License.  The full license is in
10 #  the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
13 from __future__ import absolute_import
14 
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 import codecs
19 from contextlib import contextmanager
20 import io
21 import os
22 import shutil
23 import stat
24 import sys
25 import tempfile
26 from .capture import CapturedIO, capture_output
27 from .py3compat import string_types, input, PY3
28 
29 #-----------------------------------------------------------------------------
30 # Code
31 #-----------------------------------------------------------------------------
32 
33 
34 class IOStream:
35 
36     def __init__(self,stream, fallback=None):
37         if not hasattr(stream,'write') or not hasattr(stream,'flush'):
38             if fallback is not None:
39                 stream = fallback
40             else:
41                 raise ValueError("fallback required, but not specified")
42         self.stream = stream
43         self._swrite = stream.write
44 
45         # clone all methods not overridden:
46         def clone(meth):
47             return not hasattr(self, meth) and not meth.startswith('_')
48         for meth in filter(clone, dir(stream)):
49             setattr(self, meth, getattr(stream, meth))
50 
51     def __repr__(self):
52         cls = self.__class__
53         tpl = '{mod}.{cls}({args})'
54         return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
55 
56     def write(self,data):
57         try:
58             self._swrite(data)
59         except:
60             try:
61                 # print handles some unicode issues which may trip a plain
62                 # write() call.  Emulate write() by using an empty end
63                 # argument.
64                 print(data, end='', file=self.stream)
65             except:
66                 # if we get here, something is seriously broken.
67                 print('ERROR - failed to write data to stream:', self.stream,
68                       file=sys.stderr)
69 
70     def writelines(self, lines):
71         if isinstance(lines, string_types):
72             lines = [lines]
73         for line in lines:
74             self.write(line)
75 
76     # This class used to have a writeln method, but regular files and streams
77     # in Python don't have this method. We need to keep this completely
78     # compatible so we removed it.
79 
80     @property
81     def closed(self):
82         return self.stream.closed
83 
84     def close(self):
85         pass
86 
87 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
88 devnull = open(os.devnull, 'w') 
89 stdin = IOStream(sys.stdin, fallback=devnull)
90 stdout = IOStream(sys.stdout, fallback=devnull)
91 stderr = IOStream(sys.stderr, fallback=devnull)
92 
93 class IOTerm:
94     """ Term holds the file or file-like objects for handling I/O operations.
95 
96     These are normally just sys.stdin, sys.stdout and sys.stderr but for
97     Windows they can can replaced to allow editing the strings before they are
98     displayed."""
99 
100     # In the future, having IPython channel all its I/O operations through
101     # this class will make it easier to embed it into other environments which
102     # are not a normal terminal (such as a GUI-based shell)
103     def __init__(self, stdin=None, stdout=None, stderr=None):
104         mymodule = sys.modules[__name__]
105         self.stdin  = IOStream(stdin, mymodule.stdin)
106         self.stdout = IOStream(stdout, mymodule.stdout)
107         self.stderr = IOStream(stderr, mymodule.stderr)
108 
109 
110 class Tee(object):
111     """A class to duplicate an output stream to stdout/err.
112 
113     This works in a manner very similar to the Unix 'tee' command.
114 
115     When the object is closed or deleted, it closes the original file given to
116     it for duplication.
117     """
118     # Inspired by:
119     # http://mail.python.org/pipermail/python-list/2007-May/442737.html
120 
121     def __init__(self, file_or_name, mode="w", channel='stdout'):
122         """Construct a new Tee object.
123 
124         Parameters
125         ----------
126         file_or_name : filename or open filehandle (writable)
127           File that will be duplicated
128 
129         mode : optional, valid mode for open().
130           If a filename was give, open with this mode.
131 
132         channel : str, one of ['stdout', 'stderr']
133         """
134         if channel not in ['stdout', 'stderr']:
135             raise ValueError('Invalid channel spec %s' % channel)
136 
137         if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
138             self.file = file_or_name
139         else:
140             self.file = open(file_or_name, mode)
141         self.channel = channel
142         self.ostream = getattr(sys, channel)
143         setattr(sys, channel, self)
144         self._closed = False
145 
146     def close(self):
147         """Close the file and restore the channel."""
148         self.flush()
149         setattr(sys, self.channel, self.ostream)
150         self.file.close()
151         self._closed = True
152 
153     def write(self, data):
154         """Write data to both channels."""
155         self.file.write(data)
156         self.ostream.write(data)
157         self.ostream.flush()
158 
159     def flush(self):
160         """Flush both channels."""
161         self.file.flush()
162         self.ostream.flush()
163 
164     def __del__(self):
165         if not self._closed:
166             self.close()
167 
168 
169 def ask_yes_no(prompt, default=None, interrupt=None):
170     """Asks a question and returns a boolean (y/n) answer.
171 
172     If default is given (one of 'y','n'), it is used if the user input is
173     empty. If interrupt is given (one of 'y','n'), it is used if the user
174     presses Ctrl-C. Otherwise the question is repeated until an answer is
175     given.
176 
177     An EOF is treated as the default answer.  If there is no default, an
178     exception is raised to prevent infinite loops.
179 
180     Valid answers are: y/yes/n/no (match is not case sensitive)."""
181 
182     answers = {'y':True,'n':False,'yes':True,'no':False}
183     ans = None
184     while ans not in answers.keys():
185         try:
186             ans = input(prompt+' ').lower()
187             if not ans:  # response was an empty string
188                 ans = default
189         except KeyboardInterrupt:
190             if interrupt:
191                 ans = interrupt
192         except EOFError:
193             if default in answers.keys():
194                 ans = default
195                 print()
196             else:
197                 raise
198 
199     return answers[ans]
200 
201 
202 def temp_pyfile(src, ext='.py'):
203     """Make a temporary python file, return filename and filehandle.
204 
205     Parameters
206     ----------
207     src : string or list of strings (no need for ending newlines if list)
208       Source code to be written to the file.
209 
210     ext : optional, string
211       Extension for the generated file.
212 
213     Returns
214     -------
215     (filename, open filehandle)
216       It is the caller's responsibility to close the open file and unlink it.
217     """
218     fname = tempfile.mkstemp(ext)[1]
219     f = open(fname,'w')
220     f.write(src)
221     f.flush()
222     return fname, f
223 
224 def _copy_metadata(src, dst):
225     """Copy the set of metadata we want for atomic_writing.
226     
227     Permission bits and flags. We'd like to copy file ownership as well, but we
228     can't do that.
229     """
230     shutil.copymode(src, dst)
231     st = os.stat(src)
232     if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
233         os.chflags(dst, st.st_flags)
234 
235 @contextmanager
236 def atomic_writing(path, text=True, encoding='utf-8', **kwargs):
237     """Context manager to write to a file only if the entire write is successful.
238     
239     This works by creating a temporary file in the same directory, and renaming
240     it over the old file if the context is exited without an error. If other
241     file names are hard linked to the target file, this relationship will not be
242     preserved.
243     
244     On Windows, there is a small chink in the atomicity: the target file is
245     deleted before renaming the temporary file over it. This appears to be
246     unavoidable.
247     
248     Parameters
249     ----------
250     path : str
251       The target file to write to.
252      
253     text : bool, optional
254       Whether to open the file in text mode (i.e. to write unicode). Default is
255       True.
256     
257     encoding : str, optional
258       The encoding to use for files opened in text mode. Default is UTF-8.
259      
260     **kwargs
261       Passed to :func:`io.open`.
262     """
263     # realpath doesn't work on Windows: http://bugs.python.org/issue9949
264     # Luckily, we only need to resolve the file itself being a symlink, not
265     # any of its directories, so this will suffice:
266     if os.path.islink(path):
267         path = os.path.join(os.path.dirname(path), os.readlink(path))
268 
269     dirname, basename = os.path.split(path)
270     handle, tmp_path = tempfile.mkstemp(prefix=basename, dir=dirname)
271     if text:
272         fileobj = io.open(handle, 'w', encoding=encoding, **kwargs)
273     else:
274         fileobj = io.open(handle, 'wb', **kwargs)
275 
276     try:
277         yield fileobj
278     except:
279         fileobj.close()
280         os.remove(tmp_path)
281         raise
282 
283     # Flush to disk
284     fileobj.flush()
285     os.fsync(fileobj.fileno())
286 
287     # Written successfully, now rename it
288     fileobj.close()
289 
290     # Copy permission bits, access time, etc.
291     try:
292         _copy_metadata(path, tmp_path)
293     except OSError:
294         # e.g. the file didn't already exist. Ignore any failure to copy metadata
295         pass
296 
297     if os.name == 'nt' and os.path.exists(path):
298         # Rename over existing file doesn't work on Windows
299         os.remove(path)
300 
301     os.rename(tmp_path, path)
302 
303 
304 def raw_print(*args, **kw):
305     """Raw print to sys.__stdout__, otherwise identical interface to print()."""
306 
307     print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
308           file=sys.__stdout__)
309     sys.__stdout__.flush()
310 
311 
312 def raw_print_err(*args, **kw):
313     """Raw print to sys.__stderr__, otherwise identical interface to print()."""
314 
315     print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
316           file=sys.__stderr__)
317     sys.__stderr__.flush()
318 
319 
320 # Short aliases for quick debugging, do NOT use these in production code.
321 rprint = raw_print
322 rprinte = raw_print_err
323 
324 def unicode_std_stream(stream='stdout'):
325     u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
326 
327     This ignores environment variables and default encodings, to reliably write
328     unicode to stdout or stderr.
329 
330     ::
331 
332         unicode_std_stream().write(u'ł@e¶ŧ←')
333     """
334     assert stream in ('stdout', 'stderr')
335     stream  = getattr(sys, stream)
336     if PY3:
337         try:
338             stream_b = stream.buffer
339         except AttributeError:
340             # sys.stdout has been replaced - use it directly
341             return stream
342     else:
343         stream_b = stream
344 
345     return codecs.getwriter('utf-8')(stream_b)
346
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/IPython/utils/io.py b/IPython/utils/io.py
--- a/IPython/utils/io.py
+++ b/IPython/utils/io.py
@@ -267,17 +267,18 @@
         path = os.path.join(os.path.dirname(path), os.readlink(path))
 
     dirname, basename = os.path.split(path)
-    handle, tmp_path = tempfile.mkstemp(prefix=basename, dir=dirname)
+    tmp_dir = tempfile.mkdtemp(prefix=basename, dir=dirname)
+    tmp_path = os.path.join(tmp_dir, basename)
     if text:
-        fileobj = io.open(handle, 'w', encoding=encoding, **kwargs)
+        fileobj = io.open(tmp_path, 'w', encoding=encoding, **kwargs)
     else:
-        fileobj = io.open(handle, 'wb', **kwargs)
+        fileobj = io.open(tmp_path, 'wb', **kwargs)
 
     try:
         yield fileobj
     except:
         fileobj.close()
-        os.remove(tmp_path)
+        shutil.rmtree(tmp_dir)
         raise
 
     # Flush to disk
@@ -299,6 +300,7 @@
         os.remove(path)
 
     os.rename(tmp_path, path)
+    shutil.rmtree(tmp_dir)
 
 
 def raw_print(*args, **kw):

{"golden_diff": "diff --git a/IPython/utils/io.py b/IPython/utils/io.py\n--- a/IPython/utils/io.py\n+++ b/IPython/utils/io.py\n@@ -267,17 +267,18 @@\n         path = os.path.join(os.path.dirname(path), os.readlink(path))\n \n     dirname, basename = os.path.split(path)\n-    handle, tmp_path = tempfile.mkstemp(prefix=basename, dir=dirname)\n+    tmp_dir = tempfile.mkdtemp(prefix=basename, dir=dirname)\n+    tmp_path = os.path.join(tmp_dir, basename)\n     if text:\n-        fileobj = io.open(handle, 'w', encoding=encoding, **kwargs)\n+        fileobj = io.open(tmp_path, 'w', encoding=encoding, **kwargs)\n     else:\n-        fileobj = io.open(handle, 'wb', **kwargs)\n+        fileobj = io.open(tmp_path, 'wb', **kwargs)\n \n     try:\n         yield fileobj\n     except:\n         fileobj.close()\n-        os.remove(tmp_path)\n+        shutil.rmtree(tmp_dir)\n         raise\n \n     # Flush to disk\n@@ -299,6 +300,7 @@\n         os.remove(path)\n \n     os.rename(tmp_path, path)\n+    shutil.rmtree(tmp_dir)\n \n \n def raw_print(*args, **kw):\n", "issue": "atomic write umask\nReported on gitter.im/ipython/ipython by @bigzachattack \n\nSadly no one was on the chat at that time, too busy with a big bearded men \ndressed in red trying to smuggle things in our houses through the cheminee. \n\n```\nI noticed today working in master, that any new notebook I create or copy has permissions\n0o600 and ignores my umask. In IPython.utils.io.atomic_writing() uses mkstemp() to create\na temporary file for the atomic write. According to the python docs, mkstemp creates\nfiles as 0o600.\n\nAfter the write succeeds to the tmp file, _copy_metadata is called to copy the metadata\nfrom the original file to destination file. It will throw an exception if there is no\nsource file. Thus when the notebook is copied into the notebook dir, it has\npermissions 0o600.\n\nIs this desired behavior, temporary, or a bug? I work in an environment where are default\npermissions are 0o660 to allow for users to easily share information, so defaulting new\nnotebooks to 0o600 seriously inhibits this ability.\n```\n\n", "before_files": [{"content": "# encoding: utf-8\n\"\"\"\nIO related utilities.\n\"\"\"\n\n#-----------------------------------------------------------------------------\n#  Copyright (C) 2008-2011  The IPython Development Team\n#\n#  Distributed under the terms of the BSD License.  The full license is in\n#  the file COPYING, distributed as part of this software.\n#-----------------------------------------------------------------------------\nfrom __future__ import print_function\nfrom __future__ import absolute_import\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\nimport codecs\nfrom contextlib import contextmanager\nimport io\nimport os\nimport shutil\nimport stat\nimport sys\nimport tempfile\nfrom .capture import CapturedIO, capture_output\nfrom .py3compat import string_types, input, PY3\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n\n\nclass IOStream:\n\n    def __init__(self,stream, fallback=None):\n        if not hasattr(stream,'write') or not hasattr(stream,'flush'):\n            if fallback is not None:\n                stream = fallback\n            else:\n                raise ValueError(\"fallback required, but not specified\")\n        self.stream = stream\n        self._swrite = stream.write\n\n        # clone all methods not overridden:\n        def clone(meth):\n            return not hasattr(self, meth) and not meth.startswith('_')\n        for meth in filter(clone, dir(stream)):\n            setattr(self, meth, getattr(stream, meth))\n\n    def __repr__(self):\n        cls = self.__class__\n        tpl = '{mod}.{cls}({args})'\n        return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)\n\n    def write(self,data):\n        try:\n            self._swrite(data)\n        except:\n            try:\n                # print handles some unicode issues which may trip a plain\n                # write() call.  Emulate write() by using an empty end\n                # argument.\n                print(data, end='', file=self.stream)\n            except:\n                # if we get here, something is seriously broken.\n                print('ERROR - failed to write data to stream:', self.stream,\n                      file=sys.stderr)\n\n    def writelines(self, lines):\n        if isinstance(lines, string_types):\n            lines = [lines]\n        for line in lines:\n            self.write(line)\n\n    # This class used to have a writeln method, but regular files and streams\n    # in Python don't have this method. We need to keep this completely\n    # compatible so we removed it.\n\n    @property\n    def closed(self):\n        return self.stream.closed\n\n    def close(self):\n        pass\n\n# setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr\ndevnull = open(os.devnull, 'w') \nstdin = IOStream(sys.stdin, fallback=devnull)\nstdout = IOStream(sys.stdout, fallback=devnull)\nstderr = IOStream(sys.stderr, fallback=devnull)\n\nclass IOTerm:\n    \"\"\" Term holds the file or file-like objects for handling I/O operations.\n\n    These are normally just sys.stdin, sys.stdout and sys.stderr but for\n    Windows they can can replaced to allow editing the strings before they are\n    displayed.\"\"\"\n\n    # In the future, having IPython channel all its I/O operations through\n    # this class will make it easier to embed it into other environments which\n    # are not a normal terminal (such as a GUI-based shell)\n    def __init__(self, stdin=None, stdout=None, stderr=None):\n        mymodule = sys.modules[__name__]\n        self.stdin  = IOStream(stdin, mymodule.stdin)\n        self.stdout = IOStream(stdout, mymodule.stdout)\n        self.stderr = IOStream(stderr, mymodule.stderr)\n\n\nclass Tee(object):\n    \"\"\"A class to duplicate an output stream to stdout/err.\n\n    This works in a manner very similar to the Unix 'tee' command.\n\n    When the object is closed or deleted, it closes the original file given to\n    it for duplication.\n    \"\"\"\n    # Inspired by:\n    # http://mail.python.org/pipermail/python-list/2007-May/442737.html\n\n    def __init__(self, file_or_name, mode=\"w\", channel='stdout'):\n        \"\"\"Construct a new Tee object.\n\n        Parameters\n        ----------\n        file_or_name : filename or open filehandle (writable)\n          File that will be duplicated\n\n        mode : optional, valid mode for open().\n          If a filename was give, open with this mode.\n\n        channel : str, one of ['stdout', 'stderr']\n        \"\"\"\n        if channel not in ['stdout', 'stderr']:\n            raise ValueError('Invalid channel spec %s' % channel)\n\n        if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):\n            self.file = file_or_name\n        else:\n            self.file = open(file_or_name, mode)\n        self.channel = channel\n        self.ostream = getattr(sys, channel)\n        setattr(sys, channel, self)\n        self._closed = False\n\n    def close(self):\n        \"\"\"Close the file and restore the channel.\"\"\"\n        self.flush()\n        setattr(sys, self.channel, self.ostream)\n        self.file.close()\n        self._closed = True\n\n    def write(self, data):\n        \"\"\"Write data to both channels.\"\"\"\n        self.file.write(data)\n        self.ostream.write(data)\n        self.ostream.flush()\n\n    def flush(self):\n        \"\"\"Flush both channels.\"\"\"\n        self.file.flush()\n        self.ostream.flush()\n\n    def __del__(self):\n        if not self._closed:\n            self.close()\n\n\ndef ask_yes_no(prompt, default=None, interrupt=None):\n    \"\"\"Asks a question and returns a boolean (y/n) answer.\n\n    If default is given (one of 'y','n'), it is used if the user input is\n    empty. If interrupt is given (one of 'y','n'), it is used if the user\n    presses Ctrl-C. Otherwise the question is repeated until an answer is\n    given.\n\n    An EOF is treated as the default answer.  If there is no default, an\n    exception is raised to prevent infinite loops.\n\n    Valid answers are: y/yes/n/no (match is not case sensitive).\"\"\"\n\n    answers = {'y':True,'n':False,'yes':True,'no':False}\n    ans = None\n    while ans not in answers.keys():\n        try:\n            ans = input(prompt+' ').lower()\n            if not ans:  # response was an empty string\n                ans = default\n        except KeyboardInterrupt:\n            if interrupt:\n                ans = interrupt\n        except EOFError:\n            if default in answers.keys():\n                ans = default\n                print()\n            else:\n                raise\n\n    return answers[ans]\n\n\ndef temp_pyfile(src, ext='.py'):\n    \"\"\"Make a temporary python file, return filename and filehandle.\n\n    Parameters\n    ----------\n    src : string or list of strings (no need for ending newlines if list)\n      Source code to be written to the file.\n\n    ext : optional, string\n      Extension for the generated file.\n\n    Returns\n    -------\n    (filename, open filehandle)\n      It is the caller's responsibility to close the open file and unlink it.\n    \"\"\"\n    fname = tempfile.mkstemp(ext)[1]\n    f = open(fname,'w')\n    f.write(src)\n    f.flush()\n    return fname, f\n\ndef _copy_metadata(src, dst):\n    \"\"\"Copy the set of metadata we want for atomic_writing.\n    \n    Permission bits and flags. We'd like to copy file ownership as well, but we\n    can't do that.\n    \"\"\"\n    shutil.copymode(src, dst)\n    st = os.stat(src)\n    if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):\n        os.chflags(dst, st.st_flags)\n\n@contextmanager\ndef atomic_writing(path, text=True, encoding='utf-8', **kwargs):\n    \"\"\"Context manager to write to a file only if the entire write is successful.\n    \n    This works by creating a temporary file in the same directory, and renaming\n    it over the old file if the context is exited without an error. If other\n    file names are hard linked to the target file, this relationship will not be\n    preserved.\n    \n    On Windows, there is a small chink in the atomicity: the target file is\n    deleted before renaming the temporary file over it. This appears to be\n    unavoidable.\n    \n    Parameters\n    ----------\n    path : str\n      The target file to write to.\n     \n    text : bool, optional\n      Whether to open the file in text mode (i.e. to write unicode). Default is\n      True.\n    \n    encoding : str, optional\n      The encoding to use for files opened in text mode. Default is UTF-8.\n     \n    **kwargs\n      Passed to :func:`io.open`.\n    \"\"\"\n    # realpath doesn't work on Windows: http://bugs.python.org/issue9949\n    # Luckily, we only need to resolve the file itself being a symlink, not\n    # any of its directories, so this will suffice:\n    if os.path.islink(path):\n        path = os.path.join(os.path.dirname(path), os.readlink(path))\n\n    dirname, basename = os.path.split(path)\n    handle, tmp_path = tempfile.mkstemp(prefix=basename, dir=dirname)\n    if text:\n        fileobj = io.open(handle, 'w', encoding=encoding, **kwargs)\n    else:\n        fileobj = io.open(handle, 'wb', **kwargs)\n\n    try:\n        yield fileobj\n    except:\n        fileobj.close()\n        os.remove(tmp_path)\n        raise\n\n    # Flush to disk\n    fileobj.flush()\n    os.fsync(fileobj.fileno())\n\n    # Written successfully, now rename it\n    fileobj.close()\n\n    # Copy permission bits, access time, etc.\n    try:\n        _copy_metadata(path, tmp_path)\n    except OSError:\n        # e.g. the file didn't already exist. Ignore any failure to copy metadata\n        pass\n\n    if os.name == 'nt' and os.path.exists(path):\n        # Rename over existing file doesn't work on Windows\n        os.remove(path)\n\n    os.rename(tmp_path, path)\n\n\ndef raw_print(*args, **kw):\n    \"\"\"Raw print to sys.__stdout__, otherwise identical interface to print().\"\"\"\n\n    print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\\n'),\n          file=sys.__stdout__)\n    sys.__stdout__.flush()\n\n\ndef raw_print_err(*args, **kw):\n    \"\"\"Raw print to sys.__stderr__, otherwise identical interface to print().\"\"\"\n\n    print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\\n'),\n          file=sys.__stderr__)\n    sys.__stderr__.flush()\n\n\n# Short aliases for quick debugging, do NOT use these in production code.\nrprint = raw_print\nrprinte = raw_print_err\n\ndef unicode_std_stream(stream='stdout'):\n    u\"\"\"Get a wrapper to write unicode to stdout/stderr as UTF-8.\n\n    This ignores environment variables and default encodings, to reliably write\n    unicode to stdout or stderr.\n\n    ::\n\n        unicode_std_stream().write(u'\u0142@e\u00b6\u0167\u2190')\n    \"\"\"\n    assert stream in ('stdout', 'stderr')\n    stream  = getattr(sys, stream)\n    if PY3:\n        try:\n            stream_b = stream.buffer\n        except AttributeError:\n            # sys.stdout has been replaced - use it directly\n            return stream\n    else:\n        stream_b = stream\n\n    return codecs.getwriter('utf-8')(stream_b)\n", "path": "IPython/utils/io.py"}], "after_files": [{"content": "# encoding: utf-8\n\"\"\"\nIO related utilities.\n\"\"\"\n\n#-----------------------------------------------------------------------------\n#  Copyright (C) 2008-2011  The IPython Development Team\n#\n#  Distributed under the terms of the BSD License.  The full license is in\n#  the file COPYING, distributed as part of this software.\n#-----------------------------------------------------------------------------\nfrom __future__ import print_function\nfrom __future__ import absolute_import\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\nimport codecs\nfrom contextlib import contextmanager\nimport io\nimport os\nimport shutil\nimport stat\nimport sys\nimport tempfile\nfrom .capture import CapturedIO, capture_output\nfrom .py3compat import string_types, input, PY3\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n\n\nclass IOStream:\n\n    def __init__(self,stream, fallback=None):\n        if not hasattr(stream,'write') or not hasattr(stream,'flush'):\n            if fallback is not None:\n                stream = fallback\n            else:\n                raise ValueError(\"fallback required, but not specified\")\n        self.stream = stream\n        self._swrite = stream.write\n\n        # clone all methods not overridden:\n        def clone(meth):\n            return not hasattr(self, meth) and not meth.startswith('_')\n        for meth in filter(clone, dir(stream)):\n            setattr(self, meth, getattr(stream, meth))\n\n    def __repr__(self):\n        cls = self.__class__\n        tpl = '{mod}.{cls}({args})'\n        return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)\n\n    def write(self,data):\n        try:\n            self._swrite(data)\n        except:\n            try:\n                # print handles some unicode issues which may trip a plain\n                # write() call.  Emulate write() by using an empty end\n                # argument.\n                print(data, end='', file=self.stream)\n            except:\n                # if we get here, something is seriously broken.\n                print('ERROR - failed to write data to stream:', self.stream,\n                      file=sys.stderr)\n\n    def writelines(self, lines):\n        if isinstance(lines, string_types):\n            lines = [lines]\n        for line in lines:\n            self.write(line)\n\n    # This class used to have a writeln method, but regular files and streams\n    # in Python don't have this method. We need to keep this completely\n    # compatible so we removed it.\n\n    @property\n    def closed(self):\n        return self.stream.closed\n\n    def close(self):\n        pass\n\n# setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr\ndevnull = open(os.devnull, 'w') \nstdin = IOStream(sys.stdin, fallback=devnull)\nstdout = IOStream(sys.stdout, fallback=devnull)\nstderr = IOStream(sys.stderr, fallback=devnull)\n\nclass IOTerm:\n    \"\"\" Term holds the file or file-like objects for handling I/O operations.\n\n    These are normally just sys.stdin, sys.stdout and sys.stderr but for\n    Windows they can can replaced to allow editing the strings before they are\n    displayed.\"\"\"\n\n    # In the future, having IPython channel all its I/O operations through\n    # this class will make it easier to embed it into other environments which\n    # are not a normal terminal (such as a GUI-based shell)\n    def __init__(self, stdin=None, stdout=None, stderr=None):\n        mymodule = sys.modules[__name__]\n        self.stdin  = IOStream(stdin, mymodule.stdin)\n        self.stdout = IOStream(stdout, mymodule.stdout)\n        self.stderr = IOStream(stderr, mymodule.stderr)\n\n\nclass Tee(object):\n    \"\"\"A class to duplicate an output stream to stdout/err.\n\n    This works in a manner very similar to the Unix 'tee' command.\n\n    When the object is closed or deleted, it closes the original file given to\n    it for duplication.\n    \"\"\"\n    # Inspired by:\n    # http://mail.python.org/pipermail/python-list/2007-May/442737.html\n\n    def __init__(self, file_or_name, mode=\"w\", channel='stdout'):\n        \"\"\"Construct a new Tee object.\n\n        Parameters\n        ----------\n        file_or_name : filename or open filehandle (writable)\n          File that will be duplicated\n\n        mode : optional, valid mode for open().\n          If a filename was give, open with this mode.\n\n        channel : str, one of ['stdout', 'stderr']\n        \"\"\"\n        if channel not in ['stdout', 'stderr']:\n            raise ValueError('Invalid channel spec %s' % channel)\n\n        if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):\n            self.file = file_or_name\n        else:\n            self.file = open(file_or_name, mode)\n        self.channel = channel\n        self.ostream = getattr(sys, channel)\n        setattr(sys, channel, self)\n        self._closed = False\n\n    def close(self):\n        \"\"\"Close the file and restore the channel.\"\"\"\n        self.flush()\n        setattr(sys, self.channel, self.ostream)\n        self.file.close()\n        self._closed = True\n\n    def write(self, data):\n        \"\"\"Write data to both channels.\"\"\"\n        self.file.write(data)\n        self.ostream.write(data)\n        self.ostream.flush()\n\n    def flush(self):\n        \"\"\"Flush both channels.\"\"\"\n        self.file.flush()\n        self.ostream.flush()\n\n    def __del__(self):\n        if not self._closed:\n            self.close()\n\n\ndef ask_yes_no(prompt, default=None, interrupt=None):\n    \"\"\"Asks a question and returns a boolean (y/n) answer.\n\n    If default is given (one of 'y','n'), it is used if the user input is\n    empty. If interrupt is given (one of 'y','n'), it is used if the user\n    presses Ctrl-C. Otherwise the question is repeated until an answer is\n    given.\n\n    An EOF is treated as the default answer.  If there is no default, an\n    exception is raised to prevent infinite loops.\n\n    Valid answers are: y/yes/n/no (match is not case sensitive).\"\"\"\n\n    answers = {'y':True,'n':False,'yes':True,'no':False}\n    ans = None\n    while ans not in answers.keys():\n        try:\n            ans = input(prompt+' ').lower()\n            if not ans:  # response was an empty string\n                ans = default\n        except KeyboardInterrupt:\n            if interrupt:\n                ans = interrupt\n        except EOFError:\n            if default in answers.keys():\n                ans = default\n                print()\n            else:\n                raise\n\n    return answers[ans]\n\n\ndef temp_pyfile(src, ext='.py'):\n    \"\"\"Make a temporary python file, return filename and filehandle.\n\n    Parameters\n    ----------\n    src : string or list of strings (no need for ending newlines if list)\n      Source code to be written to the file.\n\n    ext : optional, string\n      Extension for the generated file.\n\n    Returns\n    -------\n    (filename, open filehandle)\n      It is the caller's responsibility to close the open file and unlink it.\n    \"\"\"\n    fname = tempfile.mkstemp(ext)[1]\n    f = open(fname,'w')\n    f.write(src)\n    f.flush()\n    return fname, f\n\ndef _copy_metadata(src, dst):\n    \"\"\"Copy the set of metadata we want for atomic_writing.\n    \n    Permission bits and flags. We'd like to copy file ownership as well, but we\n    can't do that.\n    \"\"\"\n    shutil.copymode(src, dst)\n    st = os.stat(src)\n    if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):\n        os.chflags(dst, st.st_flags)\n\n@contextmanager\ndef atomic_writing(path, text=True, encoding='utf-8', **kwargs):\n    \"\"\"Context manager to write to a file only if the entire write is successful.\n    \n    This works by creating a temporary file in the same directory, and renaming\n    it over the old file if the context is exited without an error. If other\n    file names are hard linked to the target file, this relationship will not be\n    preserved.\n    \n    On Windows, there is a small chink in the atomicity: the target file is\n    deleted before renaming the temporary file over it. This appears to be\n    unavoidable.\n    \n    Parameters\n    ----------\n    path : str\n      The target file to write to.\n     \n    text : bool, optional\n      Whether to open the file in text mode (i.e. to write unicode). Default is\n      True.\n    \n    encoding : str, optional\n      The encoding to use for files opened in text mode. Default is UTF-8.\n     \n    **kwargs\n      Passed to :func:`io.open`.\n    \"\"\"\n    # realpath doesn't work on Windows: http://bugs.python.org/issue9949\n    # Luckily, we only need to resolve the file itself being a symlink, not\n    # any of its directories, so this will suffice:\n    if os.path.islink(path):\n        path = os.path.join(os.path.dirname(path), os.readlink(path))\n\n    dirname, basename = os.path.split(path)\n    tmp_dir = tempfile.mkdtemp(prefix=basename, dir=dirname)\n    tmp_path = os.path.join(tmp_dir, basename)\n    if text:\n        fileobj = io.open(tmp_path, 'w', encoding=encoding, **kwargs)\n    else:\n        fileobj = io.open(tmp_path, 'wb', **kwargs)\n\n    try:\n        yield fileobj\n    except:\n        fileobj.close()\n        shutil.rmtree(tmp_dir)\n        raise\n\n    # Flush to disk\n    fileobj.flush()\n    os.fsync(fileobj.fileno())\n\n    # Written successfully, now rename it\n    fileobj.close()\n\n    # Copy permission bits, access time, etc.\n    try:\n        _copy_metadata(path, tmp_path)\n    except OSError:\n        # e.g. the file didn't already exist. Ignore any failure to copy metadata\n        pass\n\n    if os.name == 'nt' and os.path.exists(path):\n        # Rename over existing file doesn't work on Windows\n        os.remove(path)\n\n    os.rename(tmp_path, path)\n    shutil.rmtree(tmp_dir)\n\n\ndef raw_print(*args, **kw):\n    \"\"\"Raw print to sys.__stdout__, otherwise identical interface to print().\"\"\"\n\n    print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\\n'),\n          file=sys.__stdout__)\n    sys.__stdout__.flush()\n\n\ndef raw_print_err(*args, **kw):\n    \"\"\"Raw print to sys.__stderr__, otherwise identical interface to print().\"\"\"\n\n    print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\\n'),\n          file=sys.__stderr__)\n    sys.__stderr__.flush()\n\n\n# Short aliases for quick debugging, do NOT use these in production code.\nrprint = raw_print\nrprinte = raw_print_err\n\ndef unicode_std_stream(stream='stdout'):\n    u\"\"\"Get a wrapper to write unicode to stdout/stderr as UTF-8.\n\n    This ignores environment variables and default encodings, to reliably write\n    unicode to stdout or stderr.\n\n    ::\n\n        unicode_std_stream().write(u'\u0142@e\u00b6\u0167\u2190')\n    \"\"\"\n    assert stream in ('stdout', 'stderr')\n    stream  = getattr(sys, stream)\n    if PY3:\n        try:\n            stream_b = stream.buffer\n        except AttributeError:\n            # sys.stdout has been replaced - use it directly\n            return stream\n    else:\n        stream_b = stream\n\n    return codecs.getwriter('utf-8')(stream_b)\n", "path": "IPython/utils/io.py"}]}