|
| 1 | +Metadata-Version: 2.4 |
| 2 | +Name: atomicwrites |
| 3 | +Version: 1.4.1 |
| 4 | +Summary: Atomic file writes. |
| 5 | +Home-page: https://github.com/untitaker/python-atomicwrites |
| 6 | +Author: Markus Unterwaditzer |
| 7 | + |
| 8 | +License: MIT |
| 9 | +Classifier: License :: OSI Approved :: MIT License |
| 10 | +Classifier: Programming Language :: Python :: 2 |
| 11 | +Classifier: Programming Language :: Python :: 2.7 |
| 12 | +Classifier: Programming Language :: Python :: 3 |
| 13 | +Classifier: Programming Language :: Python :: 3.4 |
| 14 | +Classifier: Programming Language :: Python :: 3.5 |
| 15 | +Classifier: Programming Language :: Python :: 3.6 |
| 16 | +Classifier: Programming Language :: Python :: 3.7 |
| 17 | +Classifier: Programming Language :: Python :: 3.8 |
| 18 | +Classifier: Programming Language :: Python :: Implementation :: CPython |
| 19 | +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* |
| 20 | +License-File: LICENSE |
| 21 | +Dynamic: author |
| 22 | +Dynamic: author-email |
| 23 | +Dynamic: classifier |
| 24 | +Dynamic: description |
| 25 | +Dynamic: home-page |
| 26 | +Dynamic: license |
| 27 | +Dynamic: license-file |
| 28 | +Dynamic: requires-python |
| 29 | +Dynamic: summary |
| 30 | + |
| 31 | +=================== |
| 32 | +python-atomicwrites |
| 33 | +=================== |
| 34 | + |
| 35 | +.. image:: https://travis-ci.com/untitaker/python-atomicwrites.svg?branch=master |
| 36 | + :target: https://travis-ci.com/untitaker/python-atomicwrites |
| 37 | +.. image:: https://ci.appveyor.com/api/projects/status/vadc4le3c27to59x/branch/master?svg=true |
| 38 | + :target: https://ci.appveyor.com/project/untitaker/python-atomicwrites/branch/master |
| 39 | +.. image:: https://readthedocs.org/projects/python-atomicwrites/badge/?version=latest |
| 40 | + :target: https://python-atomicwrites.readthedocs.io/en/latest/?badge=latest |
| 41 | + :alt: Documentation Status |
| 42 | + |
| 43 | +**Atomic file writes.** |
| 44 | + |
| 45 | +.. code-block:: python |
| 46 | + |
| 47 | + from atomicwrites import atomic_write |
| 48 | + |
| 49 | + with atomic_write('foo.txt', overwrite=True) as f: |
| 50 | + f.write('Hello world.') |
| 51 | + # "foo.txt" doesn't exist yet. |
| 52 | + |
| 53 | + # Now it does. |
| 54 | + |
| 55 | +See `API documentation <https://python-atomicwrites.readthedocs.io/en/latest/#api>`_ for more |
| 56 | +low-level interfaces. |
| 57 | + |
| 58 | +Features that distinguish it from other similar libraries (see `Alternatives and Credit`_): |
| 59 | + |
| 60 | +- Race-free assertion that the target file doesn't yet exist. This can be |
| 61 | + controlled with the ``overwrite`` parameter. |
| 62 | + |
| 63 | +- Windows support, although not well-tested. The MSDN resources are not very |
| 64 | + explicit about which operations are atomic. I'm basing my assumptions off `a |
| 65 | + comment |
| 66 | + <https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/449bb49d-8acc-48dc-a46f-0760ceddbfc3/movefileexmovefilereplaceexisting-ntfs-same-volume-atomic?forum=windowssdk#a239bc26-eaf0-4920-9f21-440bd2be9cc8>`_ |
| 67 | + by `Doug Cook |
| 68 | + <https://social.msdn.microsoft.com/Profile/doug%20e.%20cook>`_, who appears |
| 69 | + to be a Microsoft employee: |
| 70 | + |
| 71 | + Question: Is MoveFileEx atomic if the existing and new |
| 72 | + files are both on the same drive? |
| 73 | + |
| 74 | + The simple answer is "usually, but in some cases it will silently fall-back |
| 75 | + to a non-atomic method, so don't count on it". |
| 76 | + |
| 77 | + The implementation of MoveFileEx looks something like this: [...] |
| 78 | + |
| 79 | + The problem is if the rename fails, you might end up with a CopyFile, which |
| 80 | + is definitely not atomic. |
| 81 | + |
| 82 | + If you really need atomic-or-nothing, you can try calling |
| 83 | + NtSetInformationFile, which is unsupported but is much more likely to be |
| 84 | + atomic. |
| 85 | + |
| 86 | +- Simple high-level API that wraps a very flexible class-based API. |
| 87 | + |
| 88 | +- Consistent error handling across platforms. |
| 89 | + |
| 90 | + |
| 91 | +How it works |
| 92 | +============ |
| 93 | + |
| 94 | +It uses a temporary file in the same directory as the given path. This ensures |
| 95 | +that the temporary file resides on the same filesystem. |
| 96 | + |
| 97 | +The temporary file will then be atomically moved to the target location: On |
| 98 | +POSIX, it will use ``rename`` if files should be overwritten, otherwise a |
| 99 | +combination of ``link`` and ``unlink``. On Windows, it uses MoveFileEx_ through |
| 100 | +stdlib's ``ctypes`` with the appropriate flags. |
| 101 | + |
| 102 | +Note that with ``link`` and ``unlink``, there's a timewindow where the file |
| 103 | +might be available under two entries in the filesystem: The name of the |
| 104 | +temporary file, and the name of the target file. |
| 105 | + |
| 106 | +Also note that the permissions of the target file may change this way. In some |
| 107 | +situations a ``chmod`` can be issued without any concurrency problems, but |
| 108 | +since that is not always the case, this library doesn't do it by itself. |
| 109 | + |
| 110 | +.. _MoveFileEx: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365240%28v=vs.85%29.aspx |
| 111 | + |
| 112 | +fsync |
| 113 | +----- |
| 114 | + |
| 115 | +On POSIX, ``fsync`` is invoked on the temporary file after it is written (to |
| 116 | +flush file content and metadata), and on the parent directory after the file is |
| 117 | +moved (to flush filename). |
| 118 | + |
| 119 | +``fsync`` does not take care of disks' internal buffers, but there don't seem |
| 120 | +to be any standard POSIX APIs for that. On OS X, ``fcntl`` is used with |
| 121 | +``F_FULLFSYNC`` instead of ``fsync`` for that reason. |
| 122 | + |
| 123 | +On Windows, `_commit <https://msdn.microsoft.com/en-us/library/17618685.aspx>`_ |
| 124 | +is used, but there are no guarantees about disk internal buffers. |
| 125 | + |
| 126 | +Alternatives and Credit |
| 127 | +======================= |
| 128 | + |
| 129 | +Atomicwrites is directly inspired by the following libraries (and shares a |
| 130 | +minimal amount of code): |
| 131 | + |
| 132 | +- The Trac project's `utility functions |
| 133 | + <http://www.edgewall.org/docs/tags-trac-0.11.7/epydoc/trac.util-pysrc.html>`_, |
| 134 | + also used in `Werkzeug <http://werkzeug.pocoo.org/>`_ and |
| 135 | + `mitsuhiko/python-atomicfile |
| 136 | + <https://github.com/mitsuhiko/python-atomicfile>`_. The idea to use |
| 137 | + ``ctypes`` instead of ``PyWin32`` originated there. |
| 138 | + |
| 139 | +- `abarnert/fatomic <https://github.com/abarnert/fatomic>`_. Windows support |
| 140 | + (based on ``PyWin32``) was originally taken from there. |
| 141 | + |
| 142 | +Other alternatives to atomicwrites include: |
| 143 | + |
| 144 | +- `sashka/atomicfile <https://github.com/sashka/atomicfile>`_. Originally I |
| 145 | + considered using that, but at the time it was lacking a lot of features I |
| 146 | + needed (Windows support, overwrite-parameter, overriding behavior through |
| 147 | + subclassing). |
| 148 | + |
| 149 | +- The `Boltons library collection <https://github.com/mahmoud/boltons>`_ |
| 150 | + features a class for atomic file writes, which seems to have a very similar |
| 151 | + ``overwrite`` parameter. It is lacking Windows support though. |
| 152 | + |
| 153 | +License |
| 154 | +======= |
| 155 | + |
| 156 | +Licensed under the MIT, see ``LICENSE``. |
0 commit comments