r"""Replaces this file with new content.

        This context manager gives you two file objects, (r, w), where r is
        readable and has the current content of the file, and w is writable
        and will replace the file at the end of the context (unless an
        exception is raised, in which case it is rolled back).

        Keyword arguments will be used for both files, unless they are prefixed
        with ``read_`` or ``write_``. For instance::

            with Path('test.txt').rewrite(read_newline='\n',
                                          write_newline='\r\n') as (r, w):
                w.write(r.read())

        :param name: Path component to append to this path before opening the
            file.

        :param temp: Temporary file name to write, and then move over this one.
            By default it's this filename with a ``~`` suffix.

        :param tempext: Extension to add to this file to get the temporary file
            to write then move over this one. Defaults to ``~``.

def rewrite(self, mode='r', name=None, temp=None, tempext='~', **kwargs):
        r"""Replaces this file with new content.

        This context manager gives you two file objects, (r, w), where r is
        readable and has the current content of the file, and w is writable
        and will replace the file at the end of the context (unless an
        exception is raised, in which case it is rolled back).

        Keyword arguments will be used for both files, unless they are prefixed
        with ``read_`` or ``write_``. For instance::

            with Path('test.txt').rewrite(read_newline='\n',
                                          write_newline='\r\n') as (r, w):
                w.write(r.read())

        :param name: Path component to append to this path before opening the
            file.

        :param temp: Temporary file name to write, and then move over this one.
            By default it's this filename with a ``~`` suffix.

        :param tempext: Extension to add to this file to get the temporary file
            to write then move over this one. Defaults to ``~``.
        """
        if name is not None:
            pathr = self / name
        else:
            pathr = self
        for m in 'war+':
            mode = mode.replace(m, '')

        # Build options
        common_kwargs = {}
        readable_kwargs = {}
        writable_kwargs = {}
        for key, value in kwargs.items():
            if key.startswith('read_'):
                readable_kwargs[key[5:]] = value
            elif key.startswith('write_'):
                writable_kwargs[key[6:]] = value
            else:
                common_kwargs[key] = value
        readable_kwargs = dict_union(common_kwargs, readable_kwargs)
        writable_kwargs = dict_union(common_kwargs, writable_kwargs)

        with pathr.open('r' + mode, **readable_kwargs) as readable:
            if temp is not None:
                pathw = Path(temp)
            else:
                pathw = pathr + tempext
            try:
                pathw.remove()
            except OSError:
                pass
            writable = pathw.open('w' + mode, **writable_kwargs)
            try:
                yield readable, writable
            except Exception:
                # Problem, delete writable
                writable.close()
                pathw.remove()
                raise
            else:
                writable.close()
        # Alright, replace
        pathr.copymode(pathw)
        pathr.remove()
        pathw.rename(pathr)