<s> import os , threading <EOL> import win32file , win32con , pywintypes <EOL> import ctypes <EOL> from . common import FSEvent , FSMonitorError <EOL> module_loaded = True <EOL> FILE_LIST_DIRECTORY = <NUM_LIT> <EOL> FILE_NOTIFY_CHANGE_LAST_ACCESS = <NUM_LIT> <EOL> FILE_NOTIFY_CHANGE_CREATION = <NUM_LIT> <EOL> action_map = { <EOL> <NUM_LIT:1> : FSEvent . Create , <EOL> <NUM_LIT:2> : FSEvent . Delete , <EOL> <NUM_LIT:3> : FSEvent . Modify , <EOL> <NUM_LIT:4> : FSEvent . MoveFrom , <EOL> <NUM_LIT:5> : FSEvent . MoveTo , <EOL> } <EOL> flags_map = { <EOL> FSEvent . Access : FILE_NOTIFY_CHANGE_LAST_ACCESS , <EOL> FSEvent . Modify : win32con . FILE_NOTIFY_CHANGE_LAST_WRITE | win32con . FILE_NOTIFY_CHANGE_SIZE , <EOL> FSEvent . Attrib : win32con . FILE_NOTIFY_CHANGE_ATTRIBUTES | win32con . FILE_NOTIFY_CHANGE_SECURITY , <EOL> FSEvent . Create : FILE_NOTIFY_CHANGE_CREATION , <EOL> FSEvent . Delete : win32con . FILE_NOTIFY_CHANGE_FILE_NAME | win32con . FILE_NOTIFY_CHANGE_DIR_NAME , <EOL> FSEvent . DeleteSelf : <NUM_LIT:0> , <EOL> FSEvent . MoveFrom : win32con . FILE_NOTIFY_CHANGE_FILE_NAME | win32con . FILE_NOTIFY_CHANGE_DIR_NAME , <EOL> FSEvent . MoveTo : win32con . FILE_NOTIFY_CHANGE_FILE_NAME | win32con . FILE_NOTIFY_CHANGE_DIR_NAME , <EOL> } <EOL> def convert_flags ( flags ) : <EOL> os_flags = <NUM_LIT:0> <EOL> flag = <NUM_LIT:1> <EOL> while flag < FSEvent . All + <NUM_LIT:1> : <EOL> if flags & flag : <EOL> os_flags |= flags_map [ flag ] <EOL> flag <<= <NUM_LIT:1> <EOL> return os_flags <EOL> def get_dir_handle ( path ) : <EOL> return win32file . CreateFile ( <EOL> path , <EOL> FILE_LIST_DIRECTORY , <EOL> win32con . FILE_SHARE_READ | win32con . FILE_SHARE_WRITE | win32con . FILE_SHARE_DELETE , <EOL> None , <EOL> win32con . OPEN_EXISTING , <EOL> win32con . FILE_FLAG_BACKUP_SEMANTICS | win32con . FILE_FLAG_OVERLAPPED , <EOL> None ) <EOL> class FSMonitorWindowsError ( WindowsError , FSMonitorError ) : <EOL> pass <EOL> class FSMonitorWatch ( object ) : <EOL> def __init__ ( self , path , flags , user , recursive ) : <EOL> self . path = path <EOL> self . flags = flags <EOL> self . user = user <EOL> self . enabled = True <EOL> self . _recursive = recursive <EOL> self . _win32_flags = convert_flags ( flags ) <EOL> self . _key = None <EOL> self . _hDir = None <EOL> self . _hDir = get_dir_handle ( path ) <EOL> self . _overlapped = pywintypes . OVERLAPPED ( ) <EOL> self . _buf = ctypes . create_string_buffer ( <NUM_LIT> ) <EOL> self . _removed = False <EOL> def __del__ ( self ) : <EOL> if module_loaded : <EOL> close_watch ( self ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % self . path <EOL> def close_watch ( watch ) : <EOL> if watch . _hDir is not None : <EOL> win32file . CancelIo ( watch . _hDir ) <EOL> win32file . CloseHandle ( watch . _hDir ) <EOL> watch . _hDir = None <EOL> def read_changes ( watch ) : <EOL> win32file . ReadDirectoryChangesW ( <EOL> watch . _hDir , watch . _buf , watch . _recursive , watch . _win32_flags , <EOL> watch . _overlapped , None ) <EOL> def process_events ( watch , num ) : <EOL> for action , name in win32file . FILE_NOTIFY_INFORMATION ( watch . _buf . raw , num ) : <EOL> action = action_map . get ( action ) <EOL> if action is not None and ( action & watch . flags ) : <EOL> yield FSEvent ( watch , action , name ) <EOL> try : <EOL> read_changes ( watch ) <EOL> except pywintypes . error as e : <EOL> if e . args [ <NUM_LIT:0> ] == <NUM_LIT:5> : <EOL> close_watch ( watch ) <EOL> yield FSEvent ( watch , FSEvent . DeleteSelf ) <EOL> else : <EOL> raise FSMonitorWindowsError ( * e . args ) <EOL> class FSMonitor ( object ) : <EOL> def __init__ ( self ) : <EOL> self . __key_to_watch = { } <EOL> self . __last_key = <NUM_LIT:0> <EOL> self . __lock = threading . Lock ( ) <EOL> self . __cphandle = win32file . CreateIoCompletionPort ( - <NUM_LIT:1> , None , <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> def __del__ ( self ) : <EOL> if module_loaded : <EOL> self . close ( ) <EOL> def close ( self ) : <EOL> self . remove_all_watches ( ) <EOL> if self . __cphandle is not None : <EOL> win32file . CloseHandle ( self . __cphandle ) <EOL> self . __cphandle = None <EOL> def add_dir_watch ( self , path , flags = FSEvent . All , user = None , recursive = False ) : <EOL> try : <EOL> flags |= FSEvent . DeleteSelf <EOL> watch = FSMonitorWatch ( path , flags , user , recursive ) <EOL> with self . __lock : <EOL> key = self . __last_key <EOL> self . __last_key += <NUM_LIT:1> <EOL> watch . _key = key <EOL> self . __key_to_watch [ key ] = watch <EOL> win32file . CreateIoCompletionPort ( watch . _hDir , self . __cphandle , key , <NUM_LIT:0> ) <EOL> read_changes ( watch ) <EOL> return watch <EOL> except pywintypes . error as e : <EOL> raise FSMonitorWindowsError ( * e . args ) <EOL> def add_file_watch ( self , path , flags = FSEvent . All , user = None ) : <EOL> raise NotImplementedError ( ) <EOL> def remove_watch ( self , watch ) : <EOL> if not watch . _removed : <EOL> watch . _removed = True <EOL> try : <EOL> close_watch ( watch ) <EOL> return True <EOL> except pywintypes . error : <EOL> pass <EOL> return False <EOL> def remove_all_watches ( self ) : <EOL> with self . __lock : <EOL> watches_to_close = [ ] <EOL> for watch in self . __key_to_watch . values ( ) : <EOL> if not watch . _removed : <EOL> watch . _removed = True <EOL> watches_to_close . append ( watch ) <EOL> for watch in watches_to_close : <EOL> try : <EOL> close_watch ( watch ) <EOL> except pywintypes . error : <EOL> pass <EOL> def enable_watch ( self , watch , enable = True ) : <EOL> watch . enabled = enable <EOL> def disable_watch ( self , watch ) : <EOL> watch . enabled = False <EOL> def read_events ( self , timeout = None ) : <EOL> timeout_ms = <NUM_LIT> <EOL> if timeout is not None : <EOL> timeout_ms = int ( timeout * <NUM_LIT:1000> ) <EOL> if timeout_ms < <NUM_LIT:0> or timeout_ms >= <NUM_LIT> : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> try : <EOL> events = [ ] <EOL> rc , num , key , _ = win32file . GetQueuedCompletionStatus ( self . __cphandle , timeout_ms ) <EOL> if rc == <NUM_LIT:0> : <EOL> with self . __lock : <EOL> watch = self . __key_to_watch . get ( key ) <EOL> if watch is not None and watch . enabled and not watch . _removed : <EOL> events . extend ( process_events ( watch , num ) ) <EOL> elif rc == <NUM_LIT:5> : <EOL> with self . __lock : <EOL> watch = self . __key_to_watch . get ( key ) <EOL> if watch is not None and watch . enabled : <EOL> close_watch ( watch ) <EOL> del self . __key_to_watch [ key ] <EOL> events . append ( FSEvent ( watch , FSEvent . DeleteSelf ) ) <EOL> return events <EOL> except pywintypes . error as e : <EOL> raise FSMonitorWindowsError ( * e . args ) <EOL> @ property <EOL> def watches ( self ) : <EOL> with self . __lock : <EOL> return self . __key_to_watch . values ( ) </s>
