4
4
import unicodedata
5
5
6
6
from _fsevents import (
7
- loop ,
8
- stop ,
9
- schedule ,
10
- unschedule ,
11
- CF_POLLIN ,
12
- CF_POLLOUT ,
13
- FS_IGNORESELF ,
14
- FS_FILEEVENTS ,
15
- FS_ITEMCREATED ,
16
- FS_ITEMREMOVED ,
17
- FS_ITEMINODEMETAMOD ,
18
- FS_ITEMRENAMED ,
19
- FS_ITEMMODIFIED ,
20
- FS_ITEMFINDERINFOMOD ,
21
- FS_ITEMCHANGEOWNER ,
22
- FS_ITEMXATTRMOD ,
23
- FS_ITEMISFILE ,
24
- FS_ITEMISDIR ,
25
- FS_ITEMISSYMLINK ,
7
+ FS_CFLAGFILEEVENTS ,
8
+ FS_CFLAGNONE ,
26
9
FS_EVENTIDSINCENOW ,
27
10
FS_FLAGEVENTIDSWRAPPED ,
28
- FS_FLAGNONE ,
29
11
FS_FLAGHISTORYDONE ,
30
- FS_FLAGROOTCHANGED ,
31
12
FS_FLAGKERNELDROPPED ,
32
- FS_FLAGUNMOUNT ,
33
13
FS_FLAGMOUNT ,
34
- FS_FLAGUSERDROPPED ,
35
14
FS_FLAGMUSTSCANSUBDIRS ,
36
- FS_CFLAGFILEEVENTS ,
37
- FS_CFLAGNONE ,
38
- FS_CFLAGIGNORESELF ,
39
- FS_CFLAGUSECFTYPES ,
40
- FS_CFLAGNODEFER ,
41
- FS_CFLAGWATCHROOT ,
15
+ FS_FLAGROOTCHANGED ,
16
+ FS_FLAGUNMOUNT ,
17
+ FS_FLAGUSERDROPPED ,
18
+ FS_ITEMCHANGEOWNER ,
19
+ FS_ITEMCREATED ,
20
+ FS_ITEMFINDERINFOMOD ,
21
+ FS_ITEMINODEMETAMOD ,
22
+ FS_ITEMISDIR ,
23
+ FS_ITEMISFILE ,
24
+ FS_ITEMISSYMLINK ,
25
+ FS_ITEMMODIFIED ,
26
+ FS_ITEMREMOVED ,
27
+ FS_ITEMRENAMED ,
28
+ FS_ITEMXATTRMOD ,
29
+ loop ,
30
+ schedule ,
31
+ stop ,
32
+ unschedule
42
33
)
43
34
35
+
44
36
class Mask (int ):
45
37
stringmap = {
46
- FS_FLAGMUSTSCANSUBDIRS : 'MustScanSubDirs' ,
47
- FS_FLAGUSERDROPPED : 'UserDropped' ,
48
- FS_FLAGKERNELDROPPED : 'KernelDropped' ,
49
- FS_FLAGEVENTIDSWRAPPED : 'EventIDsWrapped' ,
50
- FS_FLAGHISTORYDONE : 'HistoryDone' ,
51
- FS_FLAGROOTCHANGED : 'RootChanged' ,
52
- FS_FLAGMOUNT : 'Mount' ,
53
- FS_FLAGUNMOUNT : 'Unmount' ,
54
-
38
+ FS_FLAGMUSTSCANSUBDIRS : "MustScanSubDirs" ,
39
+ FS_FLAGUSERDROPPED : "UserDropped" ,
40
+ FS_FLAGKERNELDROPPED : "KernelDropped" ,
41
+ FS_FLAGEVENTIDSWRAPPED : "EventIDsWrapped" ,
42
+ FS_FLAGHISTORYDONE : "HistoryDone" ,
43
+ FS_FLAGROOTCHANGED : "RootChanged" ,
44
+ FS_FLAGMOUNT : "Mount" ,
45
+ FS_FLAGUNMOUNT : "Unmount" ,
55
46
# Flags when creating the stream.
56
- FS_ITEMCREATED : ' ItemCreated' ,
57
- FS_ITEMREMOVED : ' ItemRemoved' ,
58
- FS_ITEMINODEMETAMOD : ' ItemInodeMetaMod' ,
59
- FS_ITEMRENAMED : ' ItemRenamed' ,
60
- FS_ITEMMODIFIED : ' ItemModified' ,
61
- FS_ITEMFINDERINFOMOD : ' ItemFinderInfoMod' ,
62
- FS_ITEMCHANGEOWNER : ' ItemChangedOwner' ,
63
- FS_ITEMXATTRMOD : ' ItemXAttrMod' ,
64
- FS_ITEMISFILE : ' ItemIsFile' ,
65
- FS_ITEMISDIR : ' ItemIsDir' ,
66
- FS_ITEMISSYMLINK : ' ItemIsSymlink'
47
+ FS_ITEMCREATED : " ItemCreated" ,
48
+ FS_ITEMREMOVED : " ItemRemoved" ,
49
+ FS_ITEMINODEMETAMOD : " ItemInodeMetaMod" ,
50
+ FS_ITEMRENAMED : " ItemRenamed" ,
51
+ FS_ITEMMODIFIED : " ItemModified" ,
52
+ FS_ITEMFINDERINFOMOD : " ItemFinderInfoMod" ,
53
+ FS_ITEMCHANGEOWNER : " ItemChangedOwner" ,
54
+ FS_ITEMXATTRMOD : " ItemXAttrMod" ,
55
+ FS_ITEMISFILE : " ItemIsFile" ,
56
+ FS_ITEMISDIR : " ItemIsDir" ,
57
+ FS_ITEMISSYMLINK : " ItemIsSymlink" ,
67
58
}
68
59
69
60
_svals = list (stringmap .items ())
@@ -96,7 +87,8 @@ def check_path_string_type(*paths):
96
87
for path in paths :
97
88
if not isinstance (path , str ):
98
89
raise TypeError (
99
- "Path must be string, not '%s'." % type (path ).__name__ )
90
+ "Path must be string, not '%s'." % type (path ).__name__
91
+ )
100
92
101
93
102
94
class Observer (threading .Thread ):
@@ -138,16 +130,25 @@ def _schedule(self, stream):
138
130
if stream .file_events :
139
131
callback = FileEventCallback (stream .callback , stream .raw_paths )
140
132
else :
133
+
141
134
def callback (paths , masks , ids ):
142
135
for path , mask , id in zip (paths , masks , ids ):
143
136
if sys .version_info [0 ] >= 3 :
144
- path = path .decode (' utf-8' )
137
+ path = path .decode (" utf-8" )
145
138
if stream .ids is False :
146
139
stream .callback (path , mask )
147
140
elif stream .ids is True :
148
141
stream .callback (path , mask , id )
149
-
150
- schedule (self , stream , callback , stream .paths , stream .since , stream .latency , stream .cflags )
142
+
143
+ schedule (
144
+ self ,
145
+ stream ,
146
+ callback ,
147
+ stream .paths ,
148
+ stream .since ,
149
+ stream .latency ,
150
+ stream .cflags ,
151
+ )
151
152
152
153
def schedule (self , stream ):
153
154
self .lock .acquire ()
@@ -181,23 +182,26 @@ def stop(self):
181
182
self .event = None
182
183
event .set ()
183
184
185
+
184
186
class Stream (object ):
185
187
def __init__ (self , callback , * paths , ** options ):
186
- file_events = options .pop ('file_events' , False )
187
- since = options .pop ('since' ,FS_EVENTIDSINCENOW )
188
- cflags = options .pop ('flags' , FS_CFLAGNONE )
189
- latency = options .pop ('latency' , 0.01 )
190
- ids = options .pop ('ids' , False )
191
- assert len (options ) == 0 , "Invalid option(s): %s" % repr (options .keys ())
188
+ file_events = options .pop ("file_events" , False )
189
+ since = options .pop ("since" , FS_EVENTIDSINCENOW )
190
+ cflags = options .pop ("flags" , FS_CFLAGNONE )
191
+ latency = options .pop ("latency" , 0.01 )
192
+ ids = options .pop ("ids" , False )
193
+ assert len (options ) == 0 , "Invalid option(s): %s" % repr (
194
+ options .keys ()
195
+ )
192
196
check_path_string_type (* paths )
193
197
194
198
self .callback = callback
195
199
self .raw_paths = paths
196
200
197
201
# The C-extension needs the path in 8-bit form.
198
202
self .paths = [
199
- path if isinstance (path , bytes )
200
- else path . encode ( 'utf-8' ) for path in paths
203
+ path if isinstance (path , bytes ) else path . encode ( "utf-8" )
204
+ for path in paths
201
205
]
202
206
203
207
self .file_events = file_events
@@ -206,8 +210,9 @@ def __init__(self, callback, *paths, **options):
206
210
self .latency = latency
207
211
self .ids = ids
208
212
213
+
209
214
class FileEvent (object ):
210
- __slots__ = ' mask' , ' cookie' , ' name'
215
+ __slots__ = " mask" , " cookie" , " name"
211
216
212
217
def __init__ (self , mask , cookie , name ):
213
218
self .mask = mask
@@ -217,6 +222,7 @@ def __init__(self, mask, cookie, name):
217
222
def __repr__ (self ):
218
223
return repr ((self .mask , self .cookie , self .name ))
219
224
225
+
220
226
class FileEventCallback (object ):
221
227
def __init__ (self , callback , paths ):
222
228
self .snapshots = {}
@@ -234,13 +240,13 @@ def __call__(self, paths, masks, ids):
234
240
for path in sorted (paths ):
235
241
# supports UTF-8-MAC(NFD)
236
242
if not isinstance (path , unicode ):
237
- path = path .decode (' utf-8' )
238
- path = unicodedata .normalize (' NFD' , path ).encode (' utf-8' )
243
+ path = path .decode (" utf-8" )
244
+ path = unicodedata .normalize (" NFD" , path ).encode (" utf-8" )
239
245
240
246
if sys .version_info [0 ] >= 3 :
241
- path = path .decode (' utf-8' )
242
-
243
- path = path .rstrip ('/' )
247
+ path = path .decode (" utf-8" )
248
+
249
+ path = path .rstrip ("/" )
244
250
snapshot = self .snapshots [path ]
245
251
current = {}
246
252
try :
@@ -265,13 +271,15 @@ def __call__(self, paths, masks, ids):
265
271
observed .discard (name )
266
272
else :
267
273
event = created .get (snap_stat .st_ino )
268
- if ( event is not None ) :
274
+ if event is not None :
269
275
self .cookie += 1
270
276
event .mask = IN_MOVED_FROM
271
277
event .cookie = self .cookie
272
278
tmp_filename = event .name
273
279
event .name = filename
274
- events .append (FileEvent (IN_MOVED_TO , self .cookie , tmp_filename ))
280
+ events .append (
281
+ FileEvent (IN_MOVED_TO , self .cookie , tmp_filename )
282
+ )
275
283
else :
276
284
event = FileEvent (IN_DELETE , None , filename )
277
285
deleted [snap_stat .st_ino ] = event
@@ -313,3 +321,32 @@ def snapshot(self, path):
313
321
entry [obj ] = os .lstat (os .path .join (root , obj ))
314
322
except OSError :
315
323
continue
324
+
325
+
326
+ __all__ = (
327
+ FS_CFLAGFILEEVENTS ,
328
+ FS_CFLAGNONE ,
329
+ FS_EVENTIDSINCENOW ,
330
+ FS_FLAGEVENTIDSWRAPPED ,
331
+ FS_FLAGHISTORYDONE ,
332
+ FS_FLAGKERNELDROPPED ,
333
+ FS_FLAGMOUNT ,
334
+ FS_FLAGMUSTSCANSUBDIRS ,
335
+ FS_FLAGROOTCHANGED ,
336
+ FS_FLAGUNMOUNT ,
337
+ FS_FLAGUSERDROPPED ,
338
+ FS_ITEMCHANGEOWNER ,
339
+ FS_ITEMCREATED ,
340
+ FS_ITEMFINDERINFOMOD ,
341
+ FS_ITEMINODEMETAMOD ,
342
+ FS_ITEMISDIR ,
343
+ FS_ITEMISFILE ,
344
+ FS_ITEMISSYMLINK ,
345
+ FS_ITEMMODIFIED ,
346
+ FS_ITEMREMOVED ,
347
+ FS_ITEMRENAMED ,
348
+ FS_ITEMXATTRMOD ,
349
+ FileEvent ,
350
+ Stream ,
351
+ Observer ,
352
+ )
0 commit comments