+ _fdatasync = os.fsync
+
+if sys.platform.startswith('darwin'):
+ # Apparently os.fsync on OS X doesn't guarantee to sync all the way down
+ import fcntl
+ def fdatasync(fd):
+ try:
+ return fcntl.fcntl(fd, fcntl.F_FULLFSYNC)
+ except IOError as e:
+ # Fallback for file systems (SMB) that do not support F_FULLFSYNC
+ if e.errno == errno.ENOTSUP:
+ return _fdatasync(fd)
+ else:
+ raise
+else:
+ fdatasync = _fdatasync
+
+
+def partition(predicate, stream):
+ """Returns (leading_matches_it, rest_it), where leading_matches_it
+ must be completely exhausted before traversing rest_it.
+
+ """
+ stream = iter(stream)
+ ns = Nonlocal()
+ ns.first_nonmatch = None
+ def leading_matches():
+ for x in stream:
+ if predicate(x):
+ yield x
+ else:
+ ns.first_nonmatch = (x,)
+ break
+ def rest():
+ if ns.first_nonmatch:
+ yield ns.first_nonmatch[0]
+ for x in stream:
+ yield x
+ return (leading_matches(), rest())
+
+
+def lines_until_sentinel(f, sentinel, ex_type):
+ # sentinel must end with \n and must contain only one \n
+ while True:
+ line = f.readline()
+ if not (line and line.endswith('\n')):
+ raise ex_type('Hit EOF while reading line')
+ if line == sentinel:
+ return
+ yield line
+
+
+def stat_if_exists(path):
+ try:
+ return os.stat(path)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ return None