diff --git a/edbob/files.py b/edbob/files.py index f3501ba..e50a8af 100644 --- a/edbob/files.py +++ b/edbob/files.py @@ -31,9 +31,10 @@ import os import os.path import shutil import tempfile +import lockfile -__all__ = ['change_newlines', 'count_lines', 'temp_path'] +__all__ = ['temp_path'] class DosFile(file): @@ -45,6 +46,27 @@ class DosFile(file): super(DosFile, self).write(string.replace(os.linesep, '\r\n')) +def locking_copy(src, dst): + """ + Implements a "locking" version of ``shutil.copy()``. + + This function exists to provide a more atomic method for copying a file + into a Linux folder which is being watched by a file monitor running on the + Linux machine. This is necessary because it is not practical to watch for + any particular ``pyinotify`` event in order to know when the file is "free" + - at least in the case of a simple copy. The reason for this is that + ``shutil.copy()`` first copies the file, but then will attempt to change + its attributes. Under normal circumstances it would seem best to respond + to the "create" (or "write close") event on the file, but in this case the + attribute update really must occur before the watched file is processed. + """ + + fn = os.path.basename(src) + dst = os.path.join(dst, fn) + with lockfile.FileLock(dst): + shutil.copy(src, dst) + + def change_newlines(path, newline): """ Rewrites the file at ``path``, changing its newline character(s) to that of diff --git a/setup.py b/setup.py index f908d4d..6317aab 100644 --- a/setup.py +++ b/setup.py @@ -71,6 +71,7 @@ requires = [ # package # low high 'decorator', # 3.3.2 + 'lockfile', # 0.9.1 'progressbar', # 2.3 'pytz', # 2012b ]