<commit_before># Copyright (c) 2010 <NAME> <<EMAIL>>
#
# This is free software released under the MIT license.
# See COPYING file for details, or visit:
# http://www.opensource.org/licenses/mit-license.php
#
# The file is part of FSMonitor, a file-system monitoring library.
# https://github.com/shaurz/fsmonitor

import os, threading
import win32file, win32con, pywintypes
import ctypes
from .common import FSEvent, FSMonitorError

# set to None when unloaded
module_loaded = True

FILE_LIST_DIRECTORY = 0x0001
FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x20
FILE_NOTIFY_CHANGE_CREATION = 0x40

action_map = {
    1 : FSEvent.Create,
    2 : FSEvent.Delete,
    3 : FSEvent.Modify,
    4 : FSEvent.MoveFrom,
    5 : FSEvent.MoveTo,
}

flags_map = {
    FSEvent.Access     : FILE_NOTIFY_CHANGE_LAST_ACCESS,
    FSEvent.Modify     : win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | win32con.FILE_NOTIFY_CHANGE_SIZE,
    FSEvent.Attrib     : win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | win32con.FILE_NOTIFY_CHANGE_SECURITY,
    FSEvent.Create     : FILE_NOTIFY_CHANGE_CREATION,
    FSEvent.Delete     : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
    FSEvent.DeleteSelf : 0,
    FSEvent.MoveFrom   : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
    FSEvent.MoveTo     : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
}

def convert_flags(flags):
    os_flags = 0
    flag = 1
    while flag < FSEvent.All + 1:
        if flags & flag:
            os_flags |= flags_map[flag]
        flag <<= 1
    return os_flags

def get_dir_handle(path):
    return win32file.CreateFile(
        path,
        FILE_LIST_DIRECTORY,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
        None,
        win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED,
        None)

class FSMonitorWindowsError(WindowsError, FSMonitorError):
    pass

class FSMonitorWatch(object):
    def __init__(self, path, flags, user, recursive):
        self.path = path
        self.flags = flags
        self.user = user
        self.enabled = True
        self._recursive = recursive
        self._win32_flags = convert_flags(flags)
        self._key = None
        self._hDir = get_dir_handle(path)
        self._overlapped = pywintypes.OVERLAPPED()
        self._buf = ctypes.create_string_buffer(1024)
        self._removed = False

    def __del__(self):
        if module_loaded:
            close_watch(self)

    def __repr__(self):
        return "<FSMonitorWatch %r>" % self.path

def close_watch(watch):
    if watch._hDir is not None:
        win32file.CancelIo(watch._hDir)
        win32file.CloseHandle(watch._hDir)
        watch._hDir = None

def read_changes(watch):<commit_msg>Make sure _hDir is defined before calling CreateFile otherwise __del__ may fail.<commit_after># Copyright (c) 2010 <NAME> <<EMAIL>>
#
# This is free software released under the MIT license.
# See COPYING file for details, or visit:
# http://www.opensource.org/licenses/mit-license.php
#
# The file is part of FSMonitor, a file-system monitoring library.
# https://github.com/shaurz/fsmonitor

import os, threading
import win32file, win32con, pywintypes
import ctypes
from .common import FSEvent, FSMonitorError

# set to None when unloaded
module_loaded = True

FILE_LIST_DIRECTORY = 0x0001
FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x20
FILE_NOTIFY_CHANGE_CREATION = 0x40

action_map = {
    1 : FSEvent.Create,
    2 : FSEvent.Delete,
    3 : FSEvent.Modify,
    4 : FSEvent.MoveFrom,
    5 : FSEvent.MoveTo,
}

flags_map = {
    FSEvent.Access     : FILE_NOTIFY_CHANGE_LAST_ACCESS,
    FSEvent.Modify     : win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | win32con.FILE_NOTIFY_CHANGE_SIZE,
    FSEvent.Attrib     : win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | win32con.FILE_NOTIFY_CHANGE_SECURITY,
    FSEvent.Create     : FILE_NOTIFY_CHANGE_CREATION,
    FSEvent.Delete     : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
    FSEvent.DeleteSelf : 0,
    FSEvent.MoveFrom   : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
    FSEvent.MoveTo     : win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_DIR_NAME,
}

def convert_flags(flags):
    os_flags = 0
    flag = 1
    while flag < FSEvent.All + 1:
        if flags & flag:
            os_flags |= flags_map[flag]
        flag <<= 1
    return os_flags

def get_dir_handle(path):
    return win32file.CreateFile(
        path,
        FILE_LIST_DIRECTORY,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
        None,
        win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED,
        None)

class FSMonitorWindowsError(WindowsError, FSMonitorError):
    pass

class FSMonitorWatch(object):
    def __init__(self, path, flags, user, recursive):
        self.path = path
        self.flags = flags
        self.user = user
        self.enabled = True
        self._recursive = recursive
        self._win32_flags = convert_flags(flags)
        self._key = None
        self._hDir = None
        self._hDir = get_dir_handle(path)
        self._overlapped = pywintypes.OVERLAPPED()
        self._buf = ctypes.create_string_buffer(1024)
        self._removed = False

    def __del__(self):
        if module_loaded:
            close_watch(self)

    def __repr__(self):
        return "<FSMonitorWatch %r>" % self.path

def close_watch(watch):
    if watch._hDir is not None:
        win32file.CancelIo(watch._hDir)
        win32file.CloseHandle(watch._hDir)
        watch._hDir = None

def read_changes(watch):
{'fraction_non_alphanumeric': 0.08029959937293155, 'fraction_numerical': 0.025431109562793937, 'mean_word_length': 3.2313927781871774, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6915248', 'n_tokens_mistral': 2061, 'n_tokens_neox': 1998, 'n_words': 382}