summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavemds <dave@gurumeditation.it>2013-05-12 19:15:09 +0200
committerdavemds <dave@gurumeditation.it>2013-05-12 19:15:09 +0200
commit39e16242a046e238f84e6b35955bdb2bd6573b8e (patch)
tree2dca4f229c97194f1e7ac9f78202e319aa2a715b
parent6e221b54c517195da40189aa2a67dec3306bc84d (diff)
Python-EFL: implemented ecore.FileMonitor class
Diffstat (limited to '')
-rw-r--r--INSTALL2
-rw-r--r--TODO1
-rw-r--r--efl/ecore/efl.ecore.pyx12
-rw-r--r--efl/ecore/efl.ecore_file_monitor.pxi81
-rw-r--r--include/efl.ecore.enums.pxd12
-rw-r--r--include/efl.ecore.pxd18
-rw-r--r--tests/ecore/test_09_file_monitor.py85
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 @@
9 - Tested with Cython 0.17.1 9 - Tested with Cython 0.17.1
10 10
11 * EFL core library 11 * EFL core library
12 - eo, evas, ecore, edje, elementary, edbus and emotion 12 - eo, evas, ecore, edje, emotion and elementary
13 13
14 * pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config) 14 * pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config)
15 - Windows executable (and GLib dependency) can be downloaded from 15 - 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
20==== 20====
21 21
22* ecore.Poller 22* ecore.Poller
23* ecore.FileMonitor
24* alert on signal and subprocess module usage (was in python-ecore/ecore/__init__.py) 23* alert on signal and subprocess module usage (was in python-ecore/ecore/__init__.py)
25* evas.SmartObject 24* evas.SmartObject
26* edje: complete the unit tests 25* 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
190 190
191ECORE_EXE_PRIORITY_INHERIT = 9999 191ECORE_EXE_PRIORITY_INHERIT = 9999
192 192
193
194# Ecore_File_Progress_Return: 193# Ecore_File_Progress_Return:
195ECORE_FILE_PROGRESS_CONTINUE = 0 194ECORE_FILE_PROGRESS_CONTINUE = 0
196ECORE_FILE_PROGRESS_ABORT = 1 195ECORE_FILE_PROGRESS_ABORT = 1
197 196
197# Ecore_File_Event
198ECORE_FILE_EVENT_NONE = enums.ECORE_FILE_EVENT_NONE
199ECORE_FILE_EVENT_CREATED_FILE = enums.ECORE_FILE_EVENT_CREATED_FILE
200ECORE_FILE_EVENT_CREATED_DIRECTORY = enums.ECORE_FILE_EVENT_CREATED_DIRECTORY
201ECORE_FILE_EVENT_DELETED_FILE = enums.ECORE_FILE_EVENT_DELETED_FILE
202ECORE_FILE_EVENT_DELETED_DIRECTORY = enums.ECORE_FILE_EVENT_DELETED_DIRECTORY
203ECORE_FILE_EVENT_DELETED_SELF = enums.ECORE_FILE_EVENT_DELETED_SELF
204ECORE_FILE_EVENT_MODIFIED = enums.ECORE_FILE_EVENT_MODIFIED
205ECORE_FILE_EVENT_CLOSED = enums.ECORE_FILE_EVENT_CLOSED
206
198 207
199cdef Eina_Bool _ecore_task_cb(void *data) with gil: 208cdef Eina_Bool _ecore_task_cb(void *data) with gil:
200 cdef Eo obj = <Eo>data 209 cdef Eo obj = <Eo>data
@@ -281,5 +290,6 @@ include "efl.ecore_fd_handler.pxi"
281include "efl.ecore_events.pxi" 290include "efl.ecore_events.pxi"
282include "efl.ecore_exe.pxi" 291include "efl.ecore_exe.pxi"
283include "efl.ecore_file_download.pxi" 292include "efl.ecore_file_download.pxi"
293include "efl.ecore_file_monitor.pxi"
284 294
285init() 295init()
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 @@
1# Copyright (C) 2007-2013 various contributors (see AUTHORS)
2#
3# This file is part of Python-EFL.
4#
5# Python-EFL is free software; you can redistribute it and/or
6# modify it under the terms of the GNU Lesser General Public
7# License as published by the Free Software Foundation; either
8# version 2.1 of the License, or (at your option) any later version.
9#
10# Python-EFL is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# Lesser General Public License for more details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>.
17
18from cpython cimport PyUnicode_AsUTF8String
19
20
21cdef void _file_monitor_cb(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const_char *path) with gil:
22 obj = <FileMonitor>data
23 try:
24 obj._exec_monitor(event, path)
25 except Exception, e:
26 traceback.print_exc()
27
28
29cdef class FileMonitor(object):
30 """ TODOC """
31 def __init__(self, path, monitor_cb, *args, **kargs):
32
33 if not callable(monitor_cb):
34 raise TypeError("Parameter 'monitor_cb' must be callable")
35
36 self.monitor_cb = monitor_cb
37 self.args = args
38 self.kargs = kargs
39
40 if isinstance(path, unicode): path = PyUnicode_AsUTF8String(path)
41 self.mon = ecore_file_monitor_add(
42 <const_char *>path if path is not None else NULL,
43 _file_monitor_cb, <void *>self)
44 if not self.mon:
45 raise SystemError("could not monitor '%s'" % (path))
46
47 Py_INCREF(self)
48
49 def __dealloc__(self):
50 if self.mon != NULL:
51 ecore_file_monitor_del(self.mon)
52 self.mon = NULL
53 self.monitor_cb = None
54 self.args = None
55 self.kargs = None
56
57 def __str__(self):
58 return "%s(monitor_cb=%s, args=%s, kargs=%s)" % \
59 (self.__class__.__name__, self.monitor_cb, self.args, self.kargs)
60
61 def __repr__(self):
62 return ("%s(%#x, monitor_cb=%s, args=%s, kargs=%s, refcount=%d)") % \
63 (self.__class__.__name__, <unsigned long><void *>self,
64 self.monitor_cb, self.args, self.kargs, PY_REFCOUNT(self))
65
66 cdef object _exec_monitor(self, Ecore_File_Event event, const_char *path):
67 if self.monitor_cb:
68 return self.monitor_cb(event, _ctouni(path), *self.args, **self.kargs)
69 return 0
70
71 def delete(self):
72 """ TODOC """
73 if self.mon != NULL:
74 ecore_file_monitor_del(self.mon)
75 self.mon = NULL
76 Py_DECREF(self)
77
78 property path:
79 """ TODOC """
80 def __get__(self):
81 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":
52 ctypedef enum Ecore_Animator_Source: 52 ctypedef enum Ecore_Animator_Source:
53 ECORE_ANIMATOR_SOURCE_TIMER 53 ECORE_ANIMATOR_SOURCE_TIMER
54 ECORE_ANIMATOR_SOURCE_CUSTOM 54 ECORE_ANIMATOR_SOURCE_CUSTOM
55
56
57cdef extern from "Ecore_File.h":
58 ctypedef enum Ecore_File_Event:
59 ECORE_FILE_EVENT_NONE
60 ECORE_FILE_EVENT_CREATED_FILE
61 ECORE_FILE_EVENT_CREATED_DIRECTORY
62 ECORE_FILE_EVENT_DELETED_FILE
63 ECORE_FILE_EVENT_DELETED_DIRECTORY
64 ECORE_FILE_EVENT_DELETED_SELF
65 ECORE_FILE_EVENT_MODIFIED
66 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 @@
18from efl cimport * 18from efl cimport *
19from efl.c_eo cimport Eo as cEo 19from efl.c_eo cimport Eo as cEo
20from efl.eo cimport Eo 20from efl.eo cimport Eo
21from efl.ecore.enums cimport Ecore_Fd_Handler_Flags, Ecore_Exe_Flags 21from efl.ecore.enums cimport Ecore_Fd_Handler_Flags, Ecore_Exe_Flags, \
22 Ecore_File_Event
22 23
23 24
24cdef extern from "Ecore.h": 25cdef extern from "Ecore.h":
@@ -165,9 +166,12 @@ cdef extern from "Ecore.h":
165cdef extern from "Ecore_File.h": 166cdef extern from "Ecore_File.h":
166 167
167 ctypedef struct Ecore_File_Download_Job 168 ctypedef struct Ecore_File_Download_Job
169 ctypedef struct Ecore_File_Monitor
168 170
169 ctypedef void (*Ecore_File_Download_Completion_Cb)(void *data, const_char *file, int status) 171 ctypedef void (*Ecore_File_Download_Completion_Cb)(void *data, const_char *file, int status)
170 ctypedef int (*Ecore_File_Download_Progress_Cb)(void *data, const_char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow) 172 ctypedef int (*Ecore_File_Download_Progress_Cb)(void *data, const_char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow)
173 ctypedef void (*Ecore_File_Monitor_Cb)(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const_char *path)
174
171 175
172 int ecore_file_init() 176 int ecore_file_init()
173 int ecore_file_shutdown() 177 int ecore_file_shutdown()
@@ -180,6 +184,10 @@ cdef extern from "Ecore_File.h":
180 void *data, 184 void *data,
181 Ecore_File_Download_Job **job_ret) 185 Ecore_File_Download_Job **job_ret)
182 186
187 Ecore_File_Monitor *ecore_file_monitor_add(const_char *path, Ecore_File_Monitor_Cb func, void *data)
188 void ecore_file_monitor_del(Ecore_File_Monitor *ecore_file_monitor)
189 const_char *ecore_file_monitor_path_get(Ecore_File_Monitor *ecore_file_monitor)
190
183 191
184#################################################################### 192####################################################################
185# Python classes 193# Python classes
@@ -316,3 +324,11 @@ cdef class FileDownload:
316 long int dltotal, long int dlnow, 324 long int dltotal, long int dlnow,
317 long int ultotal, long int ulnow) 325 long int ultotal, long int ulnow)
318 326
327
328cdef class FileMonitor:
329 cdef Ecore_File_Monitor *mon
330 cdef readonly object monitor_cb
331 cdef readonly object args
332 cdef readonly object kargs
333
334 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 @@
1#!/usr/bin/env python
2
3from efl import ecore
4import unittest
5import os
6import tempfile
7
8
9counters = [0, 0, 0, 0, 0, 0 , 0, 0]
10
11def monitor_cb(event, path, tmp_path):
12 """ for reference:
13 if event == ecore.ECORE_FILE_EVENT_MODIFIED:
14 print("EVENT_MODIFIED: '%s'" % path)
15 elif event == ecore.ECORE_FILE_EVENT_CLOSED:
16 print("EVENT_CLOSED: '%s'" % path)
17 elif event == ecore.ECORE_FILE_EVENT_CREATED_FILE:
18 print("ECORE_FILE_EVENT_CREATED_FILE: '%s'" % path)
19 elif event == ecore.ECORE_FILE_EVENT_CREATED_DIRECTORY:
20 print("ECORE_FILE_EVENT_CREATED_DIRECTORY: '%s'" % path)
21 elif event == ecore.ECORE_FILE_EVENT_DELETED_FILE:
22 print("ECORE_FILE_EVENT_DELETED_FILE: '%s'" % path)
23 elif event == ecore.ECORE_FILE_EVENT_DELETED_DIRECTORY:
24 print("ECORE_FILE_EVENT_DELETED_DIRECTORY: '%s'" % path)
25 elif event == ecore.ECORE_FILE_EVENT_DELETED_SELF:
26 print("ECORE_FILE_EVENT_DELETED_SELF: '%s'" % path)
27 """
28 counters[event] += 1
29
30def do_stuff(tmp_path, fm):
31 folder1 = os.path.join(tmp_path, "folder1")
32 folder2 = os.path.join(tmp_path, "folder2")
33 file1 = os.path.join(tmp_path, "file1")
34 file2 = os.path.join(tmp_path, "file2")
35
36 # this should trigger two ECORE_FILE_EVENT_CREATED_DIRECTORY
37 os.mkdir(folder1)
38 os.mkdir(folder2)
39
40 # this should trigger two ECORE_FILE_EVENT_DELETED_DIRECTORY
41 os.rmdir(folder1)
42 os.rmdir(folder2)
43
44 # this should trigger two ECORE_FILE_EVENT_CREATED_FILE
45 fp1 = open(file1, 'a')
46 fp2 = open(file2, 'a')
47
48 # this should trigger two ECORE_FILE_EVENT_MODIFIED
49 fp1.write("nothing to say")
50 fp2.write("nothing to say")
51
52 # this should trigger two ECORE_FILE_EVENT_CLOSED
53 fp1.close()
54 fp2.close()
55
56 # this should trigger two ECORE_FILE_EVENT_DELETED_FILE
57 os.remove(file1)
58 os.remove(file2)
59
60 # this should trigger one ECORE_FILE_EVENT_DELETED_SELF !!! we get two
61 os.rmdir(tmp_path)
62
63
64class TestFileMonitor(unittest.TestCase):
65 def testInit(self):
66 path = tempfile.mkdtemp()
67 fm = ecore.FileMonitor(path, monitor_cb, path)
68 self.assertIsInstance(fm, ecore.FileMonitor)
69 self.assertEqual(fm.path, path)
70
71 ecore.Timer(0.1, do_stuff, path, fm)
72 ecore.Timer(1.0, lambda: ecore.main_loop_quit())
73
74 ecore.main_loop_begin()
75 self.assertEqual(fm.path, path)
76 fm.delete()
77
78 # FIXME: we receive two ECORE_FILE_EVENT_DELETED_SELF, it's wrong
79 # should be [0, 2, 2, 2, 2, 1, 2, 2]
80 self.assertEqual(counters, [0, 2, 2, 2, 2, 2, 2, 2])
81
82
83if __name__ == '__main__':
84 unittest.main(verbosity=2)
85 ecore.shutdown()