Changes are now documented on this page: http://github.com/seb-m/pyinotify/wiki/Recent-Developments Changes in version 0.8.0: ------------------------ * Incompatible changes with version 0.7.x - Dropped support for python 2.3 (supports only CPython >= 2.4) - Changed attribute names of class Event: * 'is_dir' becomes 'dir' * 'event_name' becomes 'maskname' - Altered namespace: * Everything previously accessible under inotify.* is now accessible under pyinotify. - When meaningful, an event (instance of Event) brings a new attribute 'pathname' - Modified debugging messages: * The VERBOSE variable is removed, and is replaced by the logging module * Set the reporting level like this: log.setLevel(level) * print_err(msg) replaced by log.error(msg) - EventsCodes: * _get_event_name(mask) replaced by get_masks(mask) * EventsCodes.IN_* replaced by IN_* (avalaible at the pyinotify's scope) - Notifier: * Avoid use of ThreadedNotifier, everything can be done with Notifier and it provides more functionalities * Use Notifier.loop() method instead of using an infinite while loop Changes in version 0.6.2: ------------------------ * New features - Pathname pattern expansion: Something like python -m pyinotify /tmp/[0-9]*.gif now works. See http://www.python.org/doc/lib/module-glob.html for more details. Changes in version 0.6.0: ------------------------ * Incompatible changes List of incompatible changes in pyinotify.py: ------------------------------------------------------------------- | v0.5 | Now | |-------------------------------------------------------------------| | i1 = SimpleINotify() | wm = WatchManager() | | i2 = ThreadedINotify() | n1 = Notifier(wm) | | | n2 = ThreadedNotifier(wm) | |-------------------------------------------------------------------| | i2.start() | n2.start() | |-------------------------------------------------------------------| | i1.add_watch(...) | wm.add_watch(...) | | i2.rm_watch(...) | wm.rm_watch(...) | |-------------------------------------------------------------------| | i1.close() | n1.stop() | |-------------------------------------------------------------------| | DEBUG = True | VERBOSE = True | |-------------------------------------------------------------------| | event.isdir | event.is_dir | |-------------------------------------------------------------------| | i1.event_check() | n1.check_events() | |-------------------------------------------------------------------| | raise ProcessEventException(err) | raise ProcessEventError(err) | | raise INotifyException(err) | raise NotifierError(err) | |------------------------------------|------------------------------| | def process_default(s,a,b): | def process_default(s,event):| | pass | pass | ------------------------------------------------------------------- * New features - supported flags: IN_ONLYDIR, IN_DONT_FOLLOW, IN_MASK_ADD, IN_MOVE_SELF - auto_add: if a watch is added with this flag set to true, every new subdirectory will be automatically watched too. - possibility to pass one instance of your processing class to Notifier or ThreadedNotifier and this object will be called by default for each watch. Note, you always can give an instance to add_watch(), update_watch(). * Fixed - The pathname is appropriately updated in this case: wm.add_watch('/a/') wm.add_watch('/a/b/') echo "bar" > /a/foo.txt mv /a/foo.txt /a/b/foo.txt The necessary condition is to have watches both on the source dir and on the dst dir. - Ignored (deleted) watches are removed from watch manager. * Pending bug - Consider this case: wm.add_watch('/a/foo.txt') # where neither /a nor /a/b are watched mv /a/foo.txt /a/b/foo.txt In this case we have received IN_MOVE_SELF but we are unable to infer the new pathname. The event IN_MOVE_SELF doesn't provide this indication. Actually, the safest way to use pyinotify is to watch a top directory (say /tmp) one we don't expect be moved, and the watched items located in this directory should only be moved inside this directory or inside another watched top directory (in the same device). Example: wm.add_watch('/tmp', rec=True) mv /tmp/foo/ /tmp/bar/ [safe] mv /tmp/bar/ ~/tmp/ [unsafe] mv /tmp /tmp-new [unsafe] Changes in version 0.5.0: ------------------------ * Few namespace modifications (incompatible changes) - pyinotfiy.inotify.* becomes inotify.* this namespace is a simple wrap of inotify's features (3 systems calls, and 3 variables). - pyinotify.* unchanged. This namespace handle higher developments made on top of inotify. - python -m pyinotify now works (no need to wait python 2.4.5 :) ) * New features - You can read and update the followings variables (accessible through the namespace inotify): - max_queued_events - max_user_instances - max_user_watches Changes in version 0.4.0: ------------------------ Few things have been modified (again) to add more consistence and reliability. Reliability: it is now easy to immediately and precisely know if an operation failed or not, and on which path or wd. That, without interrupting (without raising exceptions) the monitoring. It is more consistent because once you have added a watch on a path you keep the returned wd and use it to further update or remove this watch, this is the natural way. Howewer, in case where you have lost the wd and only have the path you still might retrieve the wd with the method get_wd(path). * Incompatible changes - add_watch returns a dictionary {path: watch_descriptor, ...} where: - path is the path given as argument or a subdirectory (if rec is set to True) - watch_descriptor is the corresponding wd, which is a positive integer if the watch has been successfully added or is a negative integer if it failed. - update_watch only accepts a wd or a list of wd. Moreover, it now returns a dictionary {wd: success, ...} where: - wd is the watch directory being updated (given as argument or retrieved by rec=True). - success is boolean value. success is set to True is the update succeed, False otherwise. - rm_watch only accepts a wd or a list of wd. Moreover, it now returns a dictionary {wd: success, ...} see 'update_watch' just above. Changes in version 0.3.3: ------------------------ * bug fix and cosmetic changes. Changes in version 0.3.1: ------------------------ * Incompatible changes - Event.length removed. Changes in version 0.3.0: ------------------------ This is a development version, there are many changes from 0.2.x releases, this release must be considered as unstable. Most of the changes affects the SimpleINotify class. * Incompatible changes - No more raise an INotify Exception in case where an error occurred in the methods add_watch, update_watch, rm_watch. - Ignore update to an nonexistent watch. - Different behavior for the recursive treatment of the update_watch method. Recursively update only existing and valid watches, doesn't follow symlinks. - The method rm_watch returns a list of watch descriptor (those who were removed). * New features - two new methods: get_wd and get_path. The former takes a path and returns the associated watch descriptor, the latter takes a wd and returns a path. (returning None if the request couldn't be satisfied) - add_watch accepts a list of path as well as a single path. - update_watch and remove_watch accept both string path and int wd as argument. Note: that the preferred argument for update_watch is the path whereas the preferred one for rm_watch is the wd. - The methods rm_watch and update_watch can recursively be applied on theirs arguments. The symlinks aren't followed. Read also the next section. - rm_watch returns the list of watch descriptors of watches successfully removed. * Performances - Always prefer string path for update_watch, and int wd for rm_watch. - Always prefer to save the result of one operation e.g. add_watch for further update or remove watches with this list instead the use of the 'rec' option which is very expansive. * Exceptions vs errors vs nothing The previous versions raised exceptions on explicit errors, the drawback was to drop important informations. For example, given the list ['a-valid-path', 'non-valid-path', 'a-valid-path2'], the first item was successfully added whereas an exception was raised on the second, thus the first wd hadn't been returned to the caller, and the last item hadn't been processed. The new approach is to quietly ignore errors, process all items and to return all successfully executed operations. The benefit is to never hang up the execution of one operation, the called method will never unexpectedly fail, if all operations failed, the result is an empty list. The drawback is to not directly and explicitly report errors. This task is left to the caller, which is able to compare the input parameters to the received list. Obviously this is a subjective choice but i think this is the least worst. Anyway, feel free to send me a comment to say if in your use case this choice works or if it is really really annoying.