Python-EFL: implemented ecore.Poller, with docs and unittest.

This commit is contained in:
Davide Andreoli 2013-05-13 01:27:00 +02:00
parent fcac9e23ad
commit 1c255024d3
8 changed files with 194 additions and 3 deletions

2
TODO
View File

@ -19,14 +19,12 @@ BUGS
TODO
====
* ecore.Poller
* alert on signal and subprocess module usage (was in python-ecore/ecore/__init__.py)
* evas.SmartObject
* edje: complete the unit tests
* elm.Web need a test
* elm.PhotoCam need a test
* include python-ethumb
* include python-e_dbus (or make edbus2 ??)
* Review the internal functions and name them consistently
* Add more documentation for the use of callbacks
* Document our use of exceptions

View File

@ -0,0 +1,4 @@
:class:`efl.ecore.Poller` Class
==============================
.. autoclass:: efl.ecore.Poller

View File

@ -31,6 +31,18 @@ limited to that use, it can, for example, also be used to create a progress
bar. see :py:class:`Animator<efl.ecore.Animator>`
Pollers
-------
Ecore :py:class:`Poller<efl.ecore.Poller>` provides infrastructure for the
creation of pollers. Pollers are, in essence, callbacks that share a single
timer per type. Because not all pollers need to be called at the same frequency
the user may specify the frequency in ticks(each expiration of the shared
timer is called a tick, in ecore poller parlance) for each added poller.
Ecore pollers should only be used when the poller doesn't have specific
requirements on the exact times to poll.
Idlers
------
@ -82,6 +94,7 @@ Reference
class-timer
class-animator
class-poller
class-idler
class-idleenterer
class-idleexiter

View File

@ -242,6 +242,9 @@ 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
# Ecore_Poller_Type:
ECORE_POLLER_CORE = enums.ECORE_POLLER_CORE
cdef Eina_Bool _ecore_task_cb(void *data) with gil:
cdef Eo obj = <Eo>data
@ -323,6 +326,7 @@ def loop_time_get():
include "efl.ecore_animator.pxi"
include "efl.ecore_timer.pxi"
include "efl.ecore_poller.pxi"
include "efl.ecore_idler.pxi"
include "efl.ecore_fd_handler.pxi"
include "efl.ecore_events.pxi"

View File

@ -0,0 +1,112 @@
# 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/>.
cdef class Poller(Eo):
"""
Ecore poller provides infrastructure for the creation of pollers. Pollers
are, in essence, callbacks that share a single timer per type. Because not
all pollers need to be called at the same frequency the user may specify the
frequency in ticks(each expiration of the shared timer is called a tick, in
ecore poller parlance) for each added poller. Ecore pollers should only be
used when the poller doesn't have specific requirements on the exact times
to poll.
This architecture means that the main loop is only woken up once to handle
all pollers of that type, this will save power as the CPU has more of a
chance to go into a low power state the longer it is asleep for, so this
should be used in situations where power usage is a concern.
For now only 1 core poller type is supported: ECORE_POLLER_CORE, the default
interval for ECORE_POLLER_CORE is 0.125(or 1/8th) second.
The `interval` must be between 1 and 32768 inclusive, and must be a power of
2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768). The exact tick in which `func`
will be called is undefined, as only the interval between calls can be
defined. Ecore will endeavor to keep pollers synchronized and to call as
many in 1 wakeup event as possible. If `interval` is not a power of two, the
closest power of 2 greater than `interval` will be used.
When the poller `func` is called, it must return a value of either
ECORE_CALLBACK_RENEW(or True) or ECORE_CALLBACK_CANCEL(or False). If it
returns 1, it will be called again at the next tick, or if it returns
0 it will be deleted automatically making any references/handles for it
invalid.
Example::
def poller_cb():
print("Poller")
return True
ecore.Poller(4, poller_cb)
:param interval: The poll interval
:type interval: int
:param func: The cunction to call at every intervat
:type func: callable
:param poll_type: The ticker type to attach the poller to. Must be ECORE_POLLER_CORE
:type poll_type: Ecore_Poll_Type
"""
def __init__(self, int interval, func, pol_type=0, *args, **kargs):
if not callable(func):
raise TypeError("Parameter 'func' must be callable")
self.func = func
self.args = args
self.kargs = kargs
self._set_obj(ecore_poller_add(pol_type, interval, _ecore_task_cb, <void *>self))
def __str__(self):
return "%s Poller(func=%s, args=%s, kargs=%s)" % (Eo.__str__(self),
self.func, self.args, self.kargs)
def __repr__(self):
return "%s Poller(interval=%d, func=%s, args=%s, kargs=%s)" % (Eo.__repr__(self),
self.interval if self.obj else -1,
self.func, self.args, self.kargs)
cpdef bint _task_exec(self):
return self.func(*self.args, **self.kargs)
def delete(self):
""" Stop callback emission and free internal resources. """
ecore_poller_del(self.obj)
property interval:
""" The interval (in ticks) between each call of the poller
:type: int
"""
def __get__(self):
return ecore_poller_poller_interval_get(self.obj)
def __set__(self, int t):
ecore_poller_poller_interval_set(self.obj, t)
def interval_set(self, int t):
ecore_poller_poller_interval_set(self.obj, t)
def interval_get(self):
return ecore_poller_poller_interval_get(self.obj)
def poller_add(int t, func, *args, **kargs):
return Poller(t, func, *args, **kargs)

View File

@ -53,6 +53,9 @@ cdef extern from "Ecore.h":
ECORE_ANIMATOR_SOURCE_TIMER
ECORE_ANIMATOR_SOURCE_CUSTOM
ctypedef enum Ecore_Poller_Type:
ECORE_POLLER_CORE
cdef extern from "Ecore_File.h":
ctypedef enum Ecore_File_Event:

View File

@ -19,7 +19,7 @@ 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, \
Ecore_File_Event
Ecore_File_Event, Ecore_Poller_Type
cdef extern from "Ecore.h":
@ -28,6 +28,7 @@ cdef extern from "Ecore.h":
#
ctypedef cEo Ecore_Timer
ctypedef cEo Ecore_Animator
ctypedef cEo Ecore_Poller
ctypedef cEo Ecore_Idler
ctypedef cEo Ecore_Idle_Enterer
ctypedef cEo Ecore_Idle_Exiter
@ -105,6 +106,11 @@ cdef extern from "Ecore.h":
void ecore_animator_frametime_set(double frametime)
double ecore_animator_frametime_get()
Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type, int interval, Ecore_Task_Cb func, const_void *data)
void *ecore_poller_del(Ecore_Poller *poller)
Eina_Bool ecore_poller_poller_interval_set(Ecore_Poller *poller, int interval)
int ecore_poller_poller_interval_get(Ecore_Poller *poller)
Ecore_Timer *ecore_timer_add(double t, Ecore_Task_Cb func, void *data)
void *ecore_timer_del(Ecore_Timer *timer)
void ecore_timer_freeze(Ecore_Timer *timer)
@ -205,6 +211,13 @@ cdef class Animator(Eo):
cpdef bint _task_exec(self)
cdef class Poller(Eo):
cdef readonly object func
cdef readonly tuple args
cdef readonly dict kargs
cpdef bint _task_exec(self)
cdef class Idler(Eo):
cdef readonly object func, args, kargs
cpdef bint _task_exec(self)

View File

@ -0,0 +1,44 @@
#!/usr/bin/env python
from efl import ecore
import unittest
counters = [0, 0]
params = None
def poller_cb():
counters[0] += 1
return True
def poller_cb2(one, two, three, test):
global params
params = (one, two, three)
counters[1] += 1
return False
class TestPoller(unittest.TestCase):
def testInit(self):
p1 = ecore.Poller(4, poller_cb)
p2 = ecore.Poller(2, poller_cb2, ecore.ECORE_POLLER_CORE,
"uno", "due", three="tre", test=self)
p3 = ecore.Poller(16, lambda: ecore.main_loop_quit())
self.assertIsInstance(p1, ecore.Poller)
self.assertIsInstance(p2, ecore.Poller)
self.assertIsInstance(p3, ecore.Poller)
ecore.main_loop_begin()
self.assertEqual(counters, [4, 1])
self.assertEqual(params, ("uno", "due", "tre"))
if __name__ == '__main__':
unittest.main(verbosity=2)
ecore.shutdown()