davemds pushed a commit to branch master.
commit 39e16242a046e238f84e6b35955bdb2bd6573b8e
Author: davemds <[email protected]>
Date: Sun May 12 19:15:09 2013 +0200
Python-EFL: implemented ecore.FileMonitor class
---
INSTALL | 2 +-
TODO | 1 -
efl/ecore/efl.ecore.pyx | 12 ++++-
efl/ecore/efl.ecore_file_monitor.pxi | 81 ++++++++++++++++++++++++++++++++++
include/efl.ecore.enums.pxd | 12 +++++
include/efl.ecore.pxd | 18 +++++++-
tests/ecore/test_09_file_monitor.py | 85 ++++++++++++++++++++++++++++++++++++
7 files changed, 207 insertions(+), 4 deletions(-)
diff --git a/INSTALL b/INSTALL
index d8c749b..ce5b226 100644
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,7 @@
- Tested with Cython 0.17.1
* EFL core library
- - eo, evas, ecore, edje, elementary, edbus and emotion
+ - eo, evas, ecore, edje, emotion and elementary
* pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config)
- Windows executable (and GLib dependency) can be downloaded from
diff --git a/TODO b/TODO
index 486b027..80dddd1 100644
--- a/TODO
+++ b/TODO
@@ -20,7 +20,6 @@ TODO
====
* ecore.Poller
-* ecore.FileMonitor
* alert on signal and subprocess module usage (was in
python-ecore/ecore/__init__.py)
* evas.SmartObject
* edje: complete the unit tests
diff --git a/efl/ecore/efl.ecore.pyx b/efl/ecore/efl.ecore.pyx
index a554bac..67b9e40 100644
--- a/efl/ecore/efl.ecore.pyx
+++ b/efl/ecore/efl.ecore.pyx
@@ -190,11 +190,20 @@ ECORE_EXE_TERM_WITH_PARENT =
enums.ECORE_EXE_TERM_WITH_PARENT
ECORE_EXE_PRIORITY_INHERIT = 9999
-
# Ecore_File_Progress_Return:
ECORE_FILE_PROGRESS_CONTINUE = 0
ECORE_FILE_PROGRESS_ABORT = 1
+# Ecore_File_Event
+ECORE_FILE_EVENT_NONE = enums.ECORE_FILE_EVENT_NONE
+ECORE_FILE_EVENT_CREATED_FILE = enums.ECORE_FILE_EVENT_CREATED_FILE
+ECORE_FILE_EVENT_CREATED_DIRECTORY = enums.ECORE_FILE_EVENT_CREATED_DIRECTORY
+ECORE_FILE_EVENT_DELETED_FILE = enums.ECORE_FILE_EVENT_DELETED_FILE
+ECORE_FILE_EVENT_DELETED_DIRECTORY = enums.ECORE_FILE_EVENT_DELETED_DIRECTORY
+ECORE_FILE_EVENT_DELETED_SELF = enums.ECORE_FILE_EVENT_DELETED_SELF
+ECORE_FILE_EVENT_MODIFIED = enums.ECORE_FILE_EVENT_MODIFIED
+ECORE_FILE_EVENT_CLOSED = enums.ECORE_FILE_EVENT_CLOSED
+
cdef Eina_Bool _ecore_task_cb(void *data) with gil:
cdef Eo obj = <Eo>data
@@ -281,5 +290,6 @@ include "efl.ecore_fd_handler.pxi"
include "efl.ecore_events.pxi"
include "efl.ecore_exe.pxi"
include "efl.ecore_file_download.pxi"
+include "efl.ecore_file_monitor.pxi"
init()
diff --git a/efl/ecore/efl.ecore_file_monitor.pxi
b/efl/ecore/efl.ecore_file_monitor.pxi
new file mode 100644
index 0000000..3d9436d
--- /dev/null
+++ b/efl/ecore/efl.ecore_file_monitor.pxi
@@ -0,0 +1,81 @@
+# Copyright (C) 2007-2013 various contributors (see AUTHORS)
+#
+# This file is part of Python-EFL.
+#
+# Python-EFL is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-EFL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>.
+
+from cpython cimport PyUnicode_AsUTF8String
+
+
+cdef void _file_monitor_cb(void *data, Ecore_File_Monitor *em,
Ecore_File_Event event, const_char *path) with gil:
+ obj = <FileMonitor>data
+ try:
+ obj._exec_monitor(event, path)
+ except Exception, e:
+ traceback.print_exc()
+
+
+cdef class FileMonitor(object):
+ """ TODOC """
+ def __init__(self, path, monitor_cb, *args, **kargs):
+
+ if not callable(monitor_cb):
+ raise TypeError("Parameter 'monitor_cb' must be callable")
+
+ self.monitor_cb = monitor_cb
+ self.args = args
+ self.kargs = kargs
+
+ if isinstance(path, unicode): path = PyUnicode_AsUTF8String(path)
+ self.mon = ecore_file_monitor_add(
+ <const_char *>path if path is not None else NULL,
+ _file_monitor_cb, <void *>self)
+ if not self.mon:
+ raise SystemError("could not monitor '%s'" % (path))
+
+ Py_INCREF(self)
+
+ def __dealloc__(self):
+ if self.mon != NULL:
+ ecore_file_monitor_del(self.mon)
+ self.mon = NULL
+ self.monitor_cb = None
+ self.args = None
+ self.kargs = None
+
+ def __str__(self):
+ return "%s(monitor_cb=%s, args=%s, kargs=%s)" % \
+ (self.__class__.__name__, self.monitor_cb, self.args,
self.kargs)
+
+ def __repr__(self):
+ return ("%s(%#x, monitor_cb=%s, args=%s, kargs=%s, refcount=%d)") % \
+ (self.__class__.__name__, <unsigned long><void *>self,
+ self.monitor_cb, self.args, self.kargs, PY_REFCOUNT(self))
+
+ cdef object _exec_monitor(self, Ecore_File_Event event, const_char *path):
+ if self.monitor_cb:
+ return self.monitor_cb(event, _ctouni(path), *self.args,
**self.kargs)
+ return 0
+
+ def delete(self):
+ """ TODOC """
+ if self.mon != NULL:
+ ecore_file_monitor_del(self.mon)
+ self.mon = NULL
+ Py_DECREF(self)
+
+ property path:
+ """ TODOC """
+ def __get__(self):
+ return _ctouni(ecore_file_monitor_path_get(self.mon))
diff --git a/include/efl.ecore.enums.pxd b/include/efl.ecore.enums.pxd
index 86268d9..fe72acb 100644
--- a/include/efl.ecore.enums.pxd
+++ b/include/efl.ecore.enums.pxd
@@ -52,3 +52,15 @@ cdef extern from "Ecore.h":
ctypedef enum Ecore_Animator_Source:
ECORE_ANIMATOR_SOURCE_TIMER
ECORE_ANIMATOR_SOURCE_CUSTOM
+
+
+cdef extern from "Ecore_File.h":
+ ctypedef enum Ecore_File_Event:
+ ECORE_FILE_EVENT_NONE
+ ECORE_FILE_EVENT_CREATED_FILE
+ ECORE_FILE_EVENT_CREATED_DIRECTORY
+ ECORE_FILE_EVENT_DELETED_FILE
+ ECORE_FILE_EVENT_DELETED_DIRECTORY
+ ECORE_FILE_EVENT_DELETED_SELF
+ ECORE_FILE_EVENT_MODIFIED
+ ECORE_FILE_EVENT_CLOSED
diff --git a/include/efl.ecore.pxd b/include/efl.ecore.pxd
index 3d92871..5b7bd26 100644
--- a/include/efl.ecore.pxd
+++ b/include/efl.ecore.pxd
@@ -18,7 +18,8 @@
from efl cimport *
from efl.c_eo cimport Eo as cEo
from efl.eo cimport Eo
-from efl.ecore.enums cimport Ecore_Fd_Handler_Flags, Ecore_Exe_Flags
+from efl.ecore.enums cimport Ecore_Fd_Handler_Flags, Ecore_Exe_Flags, \
+ Ecore_File_Event
cdef extern from "Ecore.h":
@@ -165,9 +166,12 @@ cdef extern from "Ecore.h":
cdef extern from "Ecore_File.h":
ctypedef struct Ecore_File_Download_Job
+ ctypedef struct Ecore_File_Monitor
ctypedef void (*Ecore_File_Download_Completion_Cb)(void *data, const_char
*file, int status)
ctypedef int (*Ecore_File_Download_Progress_Cb)(void *data, const_char
*file, long int dltotal, long int dlnow, long int ultotal, long int ulnow)
+ ctypedef void (*Ecore_File_Monitor_Cb)(void *data, Ecore_File_Monitor *em,
Ecore_File_Event event, const_char *path)
+
int ecore_file_init()
int ecore_file_shutdown()
@@ -180,6 +184,10 @@ cdef extern from "Ecore_File.h":
void *data,
Ecore_File_Download_Job **job_ret)
+ Ecore_File_Monitor *ecore_file_monitor_add(const_char *path,
Ecore_File_Monitor_Cb func, void *data)
+ void ecore_file_monitor_del(Ecore_File_Monitor
*ecore_file_monitor)
+ const_char *ecore_file_monitor_path_get(Ecore_File_Monitor
*ecore_file_monitor)
+
####################################################################
# Python classes
@@ -316,3 +324,11 @@ cdef class FileDownload:
long int dltotal, long int dlnow,
long int ultotal, long int ulnow)
+
+cdef class FileMonitor:
+ cdef Ecore_File_Monitor *mon
+ cdef readonly object monitor_cb
+ cdef readonly object args
+ cdef readonly object kargs
+
+ cdef object _exec_monitor(self, Ecore_File_Event event, const_char *path)
diff --git a/tests/ecore/test_09_file_monitor.py
b/tests/ecore/test_09_file_monitor.py
new file mode 100644
index 0000000..9d3519e
--- /dev/null
+++ b/tests/ecore/test_09_file_monitor.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+
+from efl import ecore
+import unittest
+import os
+import tempfile
+
+
+counters = [0, 0, 0, 0, 0, 0 , 0, 0]
+
+def monitor_cb(event, path, tmp_path):
+ """ for reference:
+ if event == ecore.ECORE_FILE_EVENT_MODIFIED:
+ print("EVENT_MODIFIED: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_CLOSED:
+ print("EVENT_CLOSED: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_CREATED_FILE:
+ print("ECORE_FILE_EVENT_CREATED_FILE: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_CREATED_DIRECTORY:
+ print("ECORE_FILE_EVENT_CREATED_DIRECTORY: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_DELETED_FILE:
+ print("ECORE_FILE_EVENT_DELETED_FILE: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_DELETED_DIRECTORY:
+ print("ECORE_FILE_EVENT_DELETED_DIRECTORY: '%s'" % path)
+ elif event == ecore.ECORE_FILE_EVENT_DELETED_SELF:
+ print("ECORE_FILE_EVENT_DELETED_SELF: '%s'" % path)
+ """
+ counters[event] += 1
+
+def do_stuff(tmp_path, fm):
+ folder1 = os.path.join(tmp_path, "folder1")
+ folder2 = os.path.join(tmp_path, "folder2")
+ file1 = os.path.join(tmp_path, "file1")
+ file2 = os.path.join(tmp_path, "file2")
+
+ # this should trigger two ECORE_FILE_EVENT_CREATED_DIRECTORY
+ os.mkdir(folder1)
+ os.mkdir(folder2)
+
+ # this should trigger two ECORE_FILE_EVENT_DELETED_DIRECTORY
+ os.rmdir(folder1)
+ os.rmdir(folder2)
+
+ # this should trigger two ECORE_FILE_EVENT_CREATED_FILE
+ fp1 = open(file1, 'a')
+ fp2 = open(file2, 'a')
+
+ # this should trigger two ECORE_FILE_EVENT_MODIFIED
+ fp1.write("nothing to say")
+ fp2.write("nothing to say")
+
+ # this should trigger two ECORE_FILE_EVENT_CLOSED
+ fp1.close()
+ fp2.close()
+
+ # this should trigger two ECORE_FILE_EVENT_DELETED_FILE
+ os.remove(file1)
+ os.remove(file2)
+
+ # this should trigger one ECORE_FILE_EVENT_DELETED_SELF !!! we get two
+ os.rmdir(tmp_path)
+
+
+class TestFileMonitor(unittest.TestCase):
+ def testInit(self):
+ path = tempfile.mkdtemp()
+ fm = ecore.FileMonitor(path, monitor_cb, path)
+ self.assertIsInstance(fm, ecore.FileMonitor)
+ self.assertEqual(fm.path, path)
+
+ ecore.Timer(0.1, do_stuff, path, fm)
+ ecore.Timer(1.0, lambda: ecore.main_loop_quit())
+
+ ecore.main_loop_begin()
+ self.assertEqual(fm.path, path)
+ fm.delete()
+
+ # FIXME: we receive two ECORE_FILE_EVENT_DELETED_SELF, it's wrong
+ # should be [0, 2, 2, 2, 2, 1, 2, 2]
+ self.assertEqual(counters, [0, 2, 2, 2, 2, 2, 2, 2])
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
+ ecore.shutdown()
--
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and
their applications. This 200-page book is written by three acclaimed
leaders in the field. The early access version is available now.
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may