From 53af01c95abe622c0490b43c12439a04aa449509 Mon Sep 17 00:00:00 2001 From: Simon Poirier Date: Wed, 28 Oct 2009 06:15:15 +0000 Subject: addon test extension to check interface contraints --- diff --git a/addons/bubblemessage.py b/addons/bubblemessage.py index 6572a6a..72ff340 100644 --- a/addons/bubblemessage.py +++ b/addons/bubblemessage.py @@ -43,33 +43,28 @@ class BubbleMessage(Action): self.tail_pos = tail_pos if message: self.message = message - - self.overlay = None - self._bubble = None - self._speaker = None def do(self): """ Show the dialog """ # get or inject overlayer - self.overlay = ObjectStore().activity._overlayer + overlay = ObjectStore().activity._overlayer # FIXME: subwindows, are left to overlap this. This behaviour is # undesirable. subwindows (i.e. child of top level windows) should be # handled either by rendering over them, or by finding different way to # draw the overlay. - if not self.overlay: - self.overlay = ObjectStore().activity._overlayer - if not self._bubble: + overlay = ObjectStore().activity._overlayer + if not hasattr(self, '_bubble'): x, y = self.position # TODO: tails are relative to tailpos. They should be relative to # the speaking widget. Same of the bubble position. self._bubble = overlayer.TextBubble(text=self.message, tailpos=self.tail_pos) self._bubble.show() - self.overlay.put(self._bubble, x, y) - self.overlay.queue_draw() + overlay.put(self._bubble, x, y) + overlay.queue_draw() def undo(self): """ @@ -84,27 +79,26 @@ class BubbleMessage(Action): Enters edit mode. The action should display itself in some way, without affecting the currently running application. """ - if not self.overlay: - self.overlay = ObjectStore().activity._overlayer + overlay = ObjectStore().activity._overlayer assert not self._drag, "bubble action set to editmode twice" x, y = self.position self._bubble = overlayer.TextBubble(text=self.message, tailpos=self.tail_pos) - self.overlay.put(self._bubble, x, y) + overlay.put(self._bubble, x, y) self._bubble.show() self._drag = DragWrapper(self._bubble, self.position, True) def exit_editmode(self, *args): - x,y = self._drag.position - self.position = (int(x), int(y)) - if self._drag: + overlay = ObjectStore().activity._overlayer + if hasattr(self, '_drag'): + x,y = self._drag.position + self.position = (int(x), int(y)) self._drag.draggable = False - self._drag = None - if self._bubble: - self.overlay.remove(self._bubble) - self._bubble = None - self.overlay = None + del self._drag + if hasattr(self, '_bubble'): + overlay.remove(self._bubble) + del self._bubble __action__ = { "name" : "BubbleMessage", diff --git a/addons/clickaction.py b/addons/clickaction.py index 88c5519..fef766e 100644 --- a/addons/clickaction.py +++ b/addons/clickaction.py @@ -25,9 +25,10 @@ class ClickAction(Action): @param widget The threehish representation of the widget """ widget = TStringProperty("") - def __init__(self, widget): + def __init__(self, widget=None): Action.__init__(self) - self.widget = widget + if widget: + self.widget = widget def do(self): """ diff --git a/addons/dialogmessage.py b/addons/dialogmessage.py index 9250693..263d00a 100644 --- a/addons/dialogmessage.py +++ b/addons/dialogmessage.py @@ -30,7 +30,6 @@ class DialogMessage(Action): @param position A list of the form [x, y] """ super(DialogMessage, self).__init__() - self._dialog = None if message: self.message = message diff --git a/addons/disablewidget.py b/addons/disablewidget.py index fd88303..8aad915 100644 --- a/addons/disablewidget.py +++ b/addons/disablewidget.py @@ -21,14 +21,13 @@ from ..services import ObjectStore class DisableWidgetAction(Action): target = TStringProperty("0") - def __init__(self, target): + def __init__(self, target=None): """Constructor @param target target treeish """ Action.__init__(self) if target is not None: self.target = target - self._widget = None def do(self): """Action do""" diff --git a/addons/gtkwidgeteventfilter.py b/addons/gtkwidgeteventfilter.py index 65aa744..126c822 100644 --- a/addons/gtkwidgeteventfilter.py +++ b/addons/gtkwidgeteventfilter.py @@ -30,11 +30,10 @@ class GtkWidgetEventFilter(EventFilter): @param event_name event to attach to """ super(GtkWidgetEventFilter,self).__init__() - self._callback = None - self.object_id = object_id - self.event_name = event_name - self._widget = None - self._handler_id = None + if object_id: + self.object_id = object_id + if event_name: + self.event_name = event_name def install_handlers(self, callback, **kwargs): """install handlers diff --git a/addons/gtkwidgettypefilter.py b/addons/gtkwidgettypefilter.py index 4ffecb5..67b1e27 100644 --- a/addons/gtkwidgettypefilter.py +++ b/addons/gtkwidgettypefilter.py @@ -30,7 +30,7 @@ class GtkWidgetTypeFilter(EventFilter): text = TStringProperty("") strokes = TArrayProperty([]) - def __init__(self, object_id, text=None, strokes=None): + def __init__(self, object_id=None, text=None, strokes=None): """Constructor @param next_state default EventFilter param, passed on to EventFilter @param object_id object tree-ish identifier @@ -40,19 +40,22 @@ class GtkWidgetTypeFilter(EventFilter): At least one of text or strokes must be supplied """ super(GtkWidgetTypeFilter, self).__init__() - self.object_id = object_id - self.text = text - self._captext = "" - self.strokes = strokes - self._capstrokes = [] - self._widget = None - self._handler_id = None + if object_id: + self.object_id = object_id + if text: + self.text = text + if strokes: + self.strokes = strokes def install_handlers(self, callback, **kwargs): """install handlers @param callback default EventFilter callback arg """ super(GtkWidgetTypeFilter, self).install_handlers(callback, **kwargs) + self._captext = "" + self._capstrokes = [] + self._widget = None + self._handler_id = None logger.debug("~~~GtkWidgetTypeFilter install") activity = ObjectStore().activity if activity is None: diff --git a/addons/oncewrapper.py b/addons/oncewrapper.py index 5db3b60..9f339a4 100644 --- a/addons/oncewrapper.py +++ b/addons/oncewrapper.py @@ -26,17 +26,16 @@ class OnceWrapper(Action): action = TAddonProperty() - def __init__(self, action): + def __init__(self, action=None): Action.__init__(self) - self._called = False - self._need_undo = False - self.action = action + if action: + self.action = action def do(self): """ Do the action only on the first time """ - if not self._called: + if not hasattr(self, '_called'): self._called = True self.action.do() self._need_undo = True @@ -45,9 +44,9 @@ class OnceWrapper(Action): """ Undo the action if it's been done """ - if self._need_undo: + if hasattr(self, '_need_undo'): self.action.undo() - self._need_undo = False + del self._need_undo __action__ = { diff --git a/addons/timerevent.py b/addons/timerevent.py index 752a865..ae2c51a 100644 --- a/addons/timerevent.py +++ b/addons/timerevent.py @@ -35,7 +35,6 @@ class TimerEvent(EventFilter): super(TimerEvent,self).__init__() if timeout: self.timeout = timeout - self._handler_id = None def install_handlers(self, callback, **kwargs): """install_handlers creates the timer and starts it""" diff --git a/addons/triggereventfilter.py b/addons/triggereventfilter.py index 19544b0..2d5932b 100644 --- a/addons/triggereventfilter.py +++ b/addons/triggereventfilter.py @@ -25,13 +25,13 @@ class TriggerEventFilter(EventFilter): """ def __init__(self): EventFilter.__init__(self) - self.toggle_on_callback = False def install_handlers(self, callback, **kwargs): """ Forsakes the incoming callback function and just set the inner one. """ self._callback = self._inner_cb + self.toggle_on_callback = False def _inner_cb(self, event_filter): self.toggle_on_callback = not self.toggle_on_callback diff --git a/addons/typetextaction.py b/addons/typetextaction.py index 8b746e6..3ec41dc 100644 --- a/addons/typetextaction.py +++ b/addons/typetextaction.py @@ -28,7 +28,7 @@ class TypeTextAction(Action): widget = TStringProperty("") text = TStringProperty("") - def __init__(self, widget, text): + def __init__(self, widget=None, text=""): Action.__init__(self) self.widget = widget diff --git a/addons/widgetidentifyaction.py b/addons/widgetidentifyaction.py index 3df244b..a546e2d 100644 --- a/addons/widgetidentifyaction.py +++ b/addons/widgetidentifyaction.py @@ -21,15 +21,11 @@ from ..editor import WidgetIdentifier class WidgetIdentifyAction(Action): def __init__(self): Action.__init__(self) - self.activity = None - self._dialog = None def do(self): os = ObjectStore() if os.activity: - self.activity = os.activity - - self._dialog = WidgetIdentifier(self.activity) + self._dialog = WidgetIdentifier(os.activity) self._dialog.show() diff --git a/tests/addontests.py b/tests/addontests.py index 5fb4f61..24fc803 100644 --- a/tests/addontests.py +++ b/tests/addontests.py @@ -18,7 +18,7 @@ import unittest -from sugar.tutorius import addon +from sugar.tutorius import addon, properties class AddonTest(unittest.TestCase): def test_create_constructor_fail(self): @@ -47,4 +47,27 @@ class AddonTest(unittest.TestCase): def test_get_addon_meta(self): addon._cache = None meta = addon.get_addon_meta("BubbleMessage") - assert meta.keys() == ['mandatory_props', 'class', 'display_name', 'name', 'icon',] + expected = set(['mandatory_props', 'class', 'display_name', 'name', 'type', 'icon']) + assert not set(meta.keys()).difference(expected), "%s == %s"%(meta.keys(), expected) + + def test_reverse_lookup(self): + obj = addon.create("BubbleMessage", message="Hi!", position=[12,31]) + assert "BubbleMessage" == addon.get_name_from_type(type(obj)) + + for name in addon.list_addons(): + klass = addon.get_addon_meta(name)['class'] + assert name == addon.get_name_from_type(klass),\ + "could not reverse lookup from type '%s'"%klass.__name__ + + def test_addon_constructor(self): + for name in addon.list_addons(): + obj = addon.create(name) + # __init__ can have locals, but should not initialize attributes on + # self as non-properties attributes won't survive serialization + # through DBUS. Assignation in do() for actions or install_handlers + # for event filters is the correct way. + attribs = set(obj.__dict__.keys()).difference(obj._props.keys()+['_props', '_callback']) + assert not attribs,\ + "assignation of attribute(s) %s detected in '%s.__init__'"%(attribs, type(obj).__name__) + + diff --git a/tutorius/actions.py b/tutorius/actions.py index bb15459..641da31 100644 --- a/tutorius/actions.py +++ b/tutorius/actions.py @@ -135,8 +135,6 @@ class Action(TPropContainer): """Base class for Actions""" def __init__(self): TPropContainer.__init__(self) - self.position = (0,0) - self._drag = None def do(self, **kwargs): """ @@ -165,7 +163,7 @@ class Action(TPropContainer): self.__edit_img.set_visible_window(True) self.__edit_img.add(actionicon) - x, y = self.position + x, y = getattr(self, 'position', (0,0)) ObjectStore().activity._overlayer.put(self.__edit_img, x, y) self.__edit_img.show_all() -- cgit v0.9.1