# -*- coding: utf-8 -*-
r """
werkzeug . posixemulation
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Provides a POSIX emulation for some features that are relevant to
web applications . The main purpose is to simplify support for
systems such as Windows NT that are not 100 % POSIX compatible .
Currently this only implements a : func : ` rename ` function that
follows POSIX semantics . Eg : if the target file already exists it
will be replaced without asking .
This module was introduced in 0.6 .1 and is not a public interface .
It might become one in later versions of Werkzeug .
: copyright : ( c ) 2013 by the Werkzeug Team , see AUTHORS for more details .
: license : BSD , see LICENSE for more details .
"""
import sys
import os
import errno
import time
import random
import shutil
can_rename_open_file = False
if os . name == ' nt ' : # pragma: no cover
_rename = lambda src , dst : False
_rename_atomic = lambda src , dst : False
if sys . version_info > = ( 3 , 0 ) :
unicode = str
try :
import ctypes
_MOVEFILE_REPLACE_EXISTING = 0x1
_MOVEFILE_WRITE_THROUGH = 0x8
_MoveFileEx = ctypes . windll . kernel32 . MoveFileExW
def _rename ( src , dst ) :
if not isinstance ( src , unicode ) :
src = unicode ( src , sys . getfilesystemencoding ( ) )
if not isinstance ( dst , unicode ) :
dst = unicode ( dst , sys . getfilesystemencoding ( ) )
if _rename_atomic ( src , dst ) :
return True
return _MoveFileEx ( src , dst , _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH )
# new in Vista and Windows Server 2008
_CreateTransaction = ctypes . windll . ktmw32 . CreateTransaction
_CommitTransaction = ctypes . windll . ktmw32 . CommitTransaction
_MoveFileTransacted = ctypes . windll . kernel32 . MoveFileTransactedW
_CloseHandle = ctypes . windll . kernel32 . CloseHandle
can_rename_open_file = True
def _rename_atomic ( src , dst ) :
ta = _CreateTransaction ( None , 0 , 0 , 0 , 0 , 1000 , ' Werkzeug rename ' )
if ta == - 1 :
return False
try :
rv = _MoveFileTransacted ( src , dst , None , None ,
_MOVEFILE_REPLACE_EXISTING |
_MOVEFILE_WRITE_THROUGH , ta )
if rv :
rv = _CommitTransaction ( ta )
return rv
finally :
_CloseHandle ( ta )
except Exception :
pass
def rename ( src , dst ) :
# Try atomic or pseudo-atomic rename
if _rename ( src , dst ) :
return
# Fall back to "move away and replace"
try :
shutil . move ( src , dst )
except OSError as e :
if e . errno != errno . EEXIST :
raise
old = " %s - %08x " % ( dst , random . randint ( 0 , sys . maxint ) )
os . rename ( dst , old )
os . rename ( src , dst )
try :
os . unlink ( old )
except Exception :
pass
else :
"""
If dst on current filesystem then use
atomic rename . Otherwise , fall back to a
non - atomic copy and remove .
"""
rename = shutil . move
can_rename_open_file = True