text: #!/usr/bin/env python
  #
  # Copyright 2007 Google Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  """Monitors a directory tree for changes using win32 APIs."""
  
  
  
  
  from builtins import object
  import ctypes
  import os
  
  # FindNextChangeNotification constants (defined in FileAPI.h):
  FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001
  FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002
  FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004
  FILE_NOTIFY_CHANGE_SIZE = 0x00000008
  FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010
  FILE_NOTIFY_CHANGE_CREATION = 0x00000040
  FILE_NOTIFY_CHANGE_SECURITY = 0x00000100
  
  # WaitForSingleObject return values (defined in WinBase.h):
  WAIT_OBJECT_0 = 0x00000000
  WAIT_TIMEOUT = 0x00000102
  WAIT_FAILED = 0xffffffff
  
  INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value
  
  _INTERESTING_NOTIFICATIONS = (FILE_NOTIFY_CHANGE_FILE_NAME |
                                FILE_NOTIFY_CHANGE_DIR_NAME |
                                FILE_NOTIFY_CHANGE_ATTRIBUTES |
                                FILE_NOTIFY_CHANGE_SIZE |
                                FILE_NOTIFY_CHANGE_LAST_WRITE |
                                FILE_NOTIFY_CHANGE_CREATION |
                                FILE_NOTIFY_CHANGE_SECURITY)
  
  
  class Win32FileWatcher(object):
    """Monitors a directory tree for changes using inotify."""
  
    # TODO: evaluate whether we can directly support multiple directories.
    SUPPORTS_MULTIPLE_DIRECTORIES = False
  
    def __init__(self, directory):
      """Initializer for InotifyFileWatcher.
  
      Args:
        directory: A string representing the path to a directory that should
            be monitored for changes i.e. files and directories added, renamed,
            deleted or changed.
      """
      self._directory = os.path.abspath(directory)
      self._find_change_handle = None
  
    def start(self):
      """Start watching the directory for changes."""
      self._find_change_handle = (
          ctypes.windll.kernel32.FindFirstChangeNotificationA(
              self._directory,
              True,  # Recursive.
              _INTERESTING_NOTIFICATIONS))
      if self._find_change_handle == INVALID_HANDLE_VALUE:
        raise ctypes.WinError()
  
      if not ctypes.windll.kernel32.FindNextChangeNotification(
          self._find_change_handle):
        raise ctypes.WinError()
  
    def quit(self):
      """Stop watching the directory for changes."""
      ctypes.windll.kernel32.FindCloseChangeNotification(self._find_change_handle)
  
    def changes(self):
      """Returns the paths changed in the watched directory since the last call.
  
      start() must be called before this method.
  
      Returns:
        Returns an iterable of changed directories/files.
      """
      found_change = False
      # Loop until no new changes are found. This prevents future accesses to
      # changes from returning the list of changes that happened before this
      # call was made.
      while True:
        wait_result = ctypes.windll.kernel32.WaitForSingleObject(
            self._find_change_handle, 0)
        if wait_result == WAIT_OBJECT_0:
          if not ctypes.windll.kernel32.FindNextChangeNotification(
              self._find_change_handle):
            raise ctypes.WinError()
          found_change = True
          continue
        elif wait_result == WAIT_TIMEOUT:
          return {'-'} if found_change else set()  # TODO: implement
        elif wait_result == WAIT_FAILED:
          raise ctypes.WinError()
        else:
          assert 'Unexpected result for WaitForSingleObject: %r' % wait_result
  