Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pyfs
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
pyfs
Commits
c84b4fbb
Commit
c84b4fbb
authored
Sep 28, 2010
by
rfkelly0
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
watch_win32: use weakrefs to avoid immortal reference cycles
parent
be7b34bb
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
44 additions
and
16 deletions
+44
-16
ChangeLog
+6
-0
fs/osfs/watch_win32.py
+27
-8
fs/tests/test_watch.py
+3
-0
fs/watch.py
+8
-8
No files found.
ChangeLog
View file @
c84b4fbb
...
...
@@ -45,6 +45,12 @@
* Fixed operation of OSFS on win32 when it points to the root of a drive.
* Made SubFS a subclass of WrapFS, and moved it into its own module at
fs.wrapfs.subfs.
* OSFSWatchMixin improvements:
* ensure that immortal reference cycles aren't created.
* watch_inotify: allow more than one watcher on a single path.
* watch_win32: report errors if the filesystem does't support
ReadDirectoryChangesW.
* watch_win32: don't create immortal reference cycles.
* Fix OSFS.add_watcher on linux platforms; previous version would cancel
any watchers when a new one was added.
* MountFS: added support for mounting at the root directory, and for
...
...
fs/osfs/watch_win32.py
View file @
c84b4fbb
...
...
@@ -16,6 +16,7 @@ import struct
import
ctypes
import
ctypes.wintypes
import
traceback
import
weakref
try
:
LPVOID
=
ctypes
.
wintypes
.
LPVOID
...
...
@@ -192,6 +193,7 @@ class WatchedDirectory(object):
self
.
callback
=
callback
self
.
recursive
=
recursive
self
.
handle
=
None
self
.
error
=
None
self
.
handle
=
CreateFileW
(
path
,
FILE_LIST_DIRECTORY
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
...
...
@@ -219,9 +221,14 @@ class WatchedDirectory(object):
overlapped
.
OffsetHigh
=
0
overlapped
.
Pointer
=
0
overlapped
.
hEvent
=
0
ReadDirectoryChangesW
(
self
.
handle
,
ctypes
.
byref
(
self
.
result
),
len
(
self
.
result
),
self
.
recursive
,
self
.
flags
,
None
,
overlapped
,
None
)
try
:
ReadDirectoryChangesW
(
self
.
handle
,
ctypes
.
byref
(
self
.
result
),
len
(
self
.
result
),
self
.
recursive
,
self
.
flags
,
None
,
overlapped
,
None
)
except
WindowsError
,
e
:
self
.
error
=
e
self
.
close
()
def
complete
(
self
,
nbytes
):
if
nbytes
==
0
:
...
...
@@ -370,8 +377,11 @@ class WatchThread(threading.Thread):
try
:
while
True
:
w
=
self
.
_new_watches
.
get_nowait
()
CreateIoCompletionPort
(
w
.
handle
,
self
.
_iocp
,
hash
(
w
),
0
)
w
.
post
()
if
w
.
handle
is
not
None
:
CreateIoCompletionPort
(
w
.
handle
,
self
.
_iocp
,
hash
(
w
),
0
)
w
.
post
()
w
.
ready
.
set
()
except
Queue
.
Empty
:
pass
...
...
@@ -405,17 +415,26 @@ class OSFSWatchMixin(WatchableFSMixin):
w
=
super
(
OSFSWatchMixin
,
self
)
.
add_watcher
(
callback
,
path
,
events
,
recursive
)
syspath
=
self
.
getsyspath
(
path
)
wt
=
self
.
__get_watch_thread
()
# Careful not to create a reference cycle here.
weak_self
=
weakref
.
ref
(
self
)
def
handle_event
(
event_class
,
path
,
*
args
,
**
kwds
):
selfref
=
weak_self
()
if
selfref
is
None
:
return
try
:
path
=
self
.
unsyspath
(
path
)
path
=
self
ref
.
unsyspath
(
path
)
except
ValueError
:
pass
else
:
if
event_class
in
(
MOVED_SRC
,
MOVED_DST
)
and
args
and
args
[
0
]:
args
=
(
self
.
unsyspath
(
args
[
0
]),)
+
args
[
1
:]
event
=
event_class
(
self
,
path
,
*
args
,
**
kwds
)
args
=
(
self
ref
.
unsyspath
(
args
[
0
]),)
+
args
[
1
:]
event
=
event_class
(
self
ref
,
path
,
*
args
,
**
kwds
)
w
.
handle_event
(
event
)
w
.
_watch_objs
=
wt
.
add_watcher
(
handle_event
,
syspath
,
w
.
events
,
w
.
recursive
)
for
wd
in
w
.
_watch_objs
:
if
wd
.
error
is
not
None
:
self
.
del_watcher
(
w
)
raise
wd
.
error
return
w
@convert_os_errors
...
...
fs/tests/test_watch.py
View file @
c84b4fbb
...
...
@@ -7,6 +7,8 @@
import
os
import
sys
import
time
import
gc
import
pickle
import
unittest
from
fs.path
import
*
...
...
@@ -176,6 +178,7 @@ class WatcherTestCases:
changes
.
close
()
from
fs
import
tempfs
,
osfs
class
TestWatchers_TempFS
(
unittest
.
TestCase
,
FSTestCases
,
WatcherTestCases
):
...
...
fs/watch.py
View file @
c84b4fbb
...
...
@@ -21,6 +21,12 @@ An FS object that wants to be "watchable" must provide the following methods:
Remove the given watcher object, or any watchers associated with
the given callback.
If you would prefer to read changes from a filesystem in a blocking fashion
rather than using callbacks, you can use the function 'iter_changes' to obtain
an iterator over the change events.
"""
import
weakref
...
...
@@ -554,15 +560,9 @@ def ensure_watchable(fs,wrapper_class=PollingWatchableFS,*args,**kwds):
if
isinstance
(
fs
,
wrapper_class
):
return
fs
try
:
# Try to add a watcher to a path that's unlikely to exist.
# It's OK if the path does exist, since we remove the watcher.
# It just might be slightly slower as the fs will actually have
# to establish the watcher.
w
=
fs
.
add_watcher
(
lambda
e
:
None
,
"/somepaththatsnotlikelytoexist"
)
except
(
AttributeError
,
UnsupportedError
):
w
=
fs
.
add_watcher
(
lambda
e
:
None
,
"/"
,
recursive
=
False
)
except
(
AttributeError
,
FSError
):
return
wrapper_class
(
fs
,
*
args
,
**
kwds
)
except
FSError
:
pass
else
:
fs
.
del_watcher
(
w
)
return
fs
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment