Skip to content

Commit

Permalink
Feat: Support Python 3
Browse files Browse the repository at this point in the history
Encode filenames to bytes before passing them to ctypes;
decode from bytes when firing FSEvents.
  • Loading branch information
phdru authored and ljmccarthy committed Jul 4, 2018
1 parent 7c780a9 commit 3ee315c
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 3 deletions.
6 changes: 6 additions & 0 deletions README.rst
Expand Up @@ -8,6 +8,12 @@ Supported Platforms
* Windows (ReadDirectoryChangesW with I/O completion ports)
* Any other platform (polling)

Supported Python versions
-------------------------

* Python 2: tested with 2.7
* Python 3: tested with 3.3+ on Linux

Installation
------------

Expand Down
3 changes: 3 additions & 0 deletions fsmonitor/compat.py
@@ -0,0 +1,3 @@
import sys

PY3 = sys.version_info[0] >= 3
10 changes: 8 additions & 2 deletions fsmonitor/linux.py
Expand Up @@ -7,9 +7,10 @@
# The file is part of FSMonitor, a file-system monitoring library.
# https://github.com/shaurz/fsmonitor

import os, struct, threading, errno, select
import sys, os, struct, threading, errno, select
from ctypes import CDLL, CFUNCTYPE, POINTER, c_int, c_char_p, c_uint32, get_errno
from .common import FSEvent, FSMonitorOSError
from .compat import PY3

# set to None when unloaded
module_loaded = True
Expand Down Expand Up @@ -91,7 +92,7 @@ def parse_events(s):
i = 0
while i + 16 < len(s):
wd, mask, cookie, length = struct.unpack_from("iIII", s, i)
name = s[i+16:i+16+length].rstrip("\0")
name = s[i+16:i+16+length].rstrip(b"\0")
i += 16 + length
yield wd, mask, cookie, name

Expand Down Expand Up @@ -127,6 +128,8 @@ def close(self):

def _add_watch(self, path, flags, user, inotify_flags=0):
inotify_flags |= convert_flags(flags) | IN_DELETE_SELF
if PY3 and not isinstance(path, bytes):
path = path.encode(sys.getfilesystemencoding())
wd = inotify_add_watch(self.__fd, path, inotify_flags)
if wd == -1:
errno = get_errno()
Expand Down Expand Up @@ -174,6 +177,7 @@ def read_events(self, timeout=None):
if not module_loaded:
return events

fsencoding = sys.getfilesystemencoding()
for wd, mask, cookie, name in parse_events(s):
with self.__lock:
watch = self.__wd_to_watch.get(wd)
Expand All @@ -183,6 +187,8 @@ def read_events(self, timeout=None):
if mask & bit:
action = action_map.get(bit)
if action is not None and (action & watch.flags):
if PY3 and isinstance(name, bytes):
name = name.decode(fsencoding)
events.append(FSEvent(watch, action, name))
bit <<= 1
if mask & IN_IGNORED:
Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -24,4 +24,5 @@
platforms="Any",
install_requires=["pypiwin32; sys_platform=='win32'"],
packages=["fsmonitor"],
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*',
)
6 changes: 5 additions & 1 deletion tox.ini
@@ -1,10 +1,14 @@
[tox]
minversion = 1.8
envlist = py27
envlist = py27, py33, py34, py35, py36

[testenv]
basepython =
py27: {env:TOXPYTHON:python2.7}
py33: {env:TOXPYTHON:python3.3}
py34: {env:TOXPYTHON:python3.4}
py35: {env:TOXPYTHON:python3.5}
py36: {env:TOXPYTHON:python3.6}
deps =
pytest
commands =
Expand Down

0 comments on commit 3ee315c

Please sign in to comment.