Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar-toolkit/src/sugar/presence
diff options
context:
space:
mode:
Diffstat (limited to 'sugar-toolkit/src/sugar/presence')
-rw-r--r--sugar-toolkit/src/sugar/presence/Makefile.am9
-rw-r--r--sugar-toolkit/src/sugar/presence/Makefile.in435
-rw-r--r--sugar-toolkit/src/sugar/presence/__init__.py24
-rw-r--r--sugar-toolkit/src/sugar/presence/activity.py410
-rw-r--r--sugar-toolkit/src/sugar/presence/buddy.py239
-rw-r--r--sugar-toolkit/src/sugar/presence/presenceservice.py609
-rw-r--r--sugar-toolkit/src/sugar/presence/sugartubeconn.py63
-rw-r--r--sugar-toolkit/src/sugar/presence/test_presence.txt26
-rw-r--r--sugar-toolkit/src/sugar/presence/tubeconn.py114
9 files changed, 0 insertions, 1929 deletions
diff --git a/sugar-toolkit/src/sugar/presence/Makefile.am b/sugar-toolkit/src/sugar/presence/Makefile.am
deleted file mode 100644
index 0c4368b..0000000
--- a/sugar-toolkit/src/sugar/presence/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-sugardir = $(pythondir)/sugar/presence
-sugar_PYTHON = \
- __init__.py \
- activity.py \
- buddy.py \
- sugartubeconn.py \
- tubeconn.py \
- presenceservice.py
-
diff --git a/sugar-toolkit/src/sugar/presence/Makefile.in b/sugar-toolkit/src/sugar/presence/Makefile.in
deleted file mode 100644
index 2ec6716..0000000
--- a/sugar-toolkit/src/sugar/presence/Makefile.in
+++ /dev/null
@@ -1,435 +0,0 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = src/sugar/presence
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
- $(sugar_PYTHON)
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gnome-compiler-flags.m4 \
- $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_CLEAN_FILES =
-SOURCES =
-DIST_SOURCES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
-am__installdirs = "$(DESTDIR)$(sugardir)"
-sugarPYTHON_INSTALL = $(INSTALL_DATA)
-py_compile = $(top_srcdir)/py-compile
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ALL_LINGUAS = @ALL_LINGUAS@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CATALOGS = @CATALOGS@
-CATOBJEXT = @CATOBJEXT@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIRNAME = @DATADIRNAME@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-EXT_CFLAGS = @EXT_CFLAGS@
-EXT_LIBS = @EXT_LIBS@
-FGREP = @FGREP@
-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GMOFILES = @GMOFILES@
-GMSGFMT = @GMSGFMT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INSTOBJEXT = @INSTOBJEXT@
-INTLLIBS = @INTLLIBS@
-INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@
-INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@
-INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@
-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
-INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@
-INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@
-INTLTOOL_MERGE = @INTLTOOL_MERGE@
-INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@
-INTLTOOL_PERL = @INTLTOOL_PERL@
-INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@
-INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@
-INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@
-INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@
-INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@
-INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@
-INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@
-INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@
-INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@
-INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@
-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
-INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@
-INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@
-INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-MKINSTALLDIRS = @MKINSTALLDIRS@
-MSGFMT = @MSGFMT@
-MSGFMT_OPTS = @MSGFMT_OPTS@
-MSGMERGE = @MSGMERGE@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-POFILES = @POFILES@
-POSUB = @POSUB@
-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
-PYGTK_CODEGEN = @PYGTK_CODEGEN@
-PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
-PYTHON = @PYTHON@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-USE_NLS = @USE_NLS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-XGETTEXT = @XGETTEXT@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-sugardir = $(pythondir)/sugar/presence
-sugar_PYTHON = \
- __init__.py \
- activity.py \
- buddy.py \
- sugartubeconn.py \
- tubeconn.py \
- presenceservice.py
-
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/sugar/presence/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign src/sugar/presence/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-sugarPYTHON: $(sugar_PYTHON)
- @$(NORMAL_INSTALL)
- test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)"
- @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- f=$(am__strip_dir) \
- dlist="$$dlist $$f"; \
- echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \
- $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \
- else :; fi; \
- done; \
- if test -n "$$dlist"; then \
- if test -z "$(DESTDIR)"; then \
- PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \
- else \
- PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \
- fi; \
- else :; fi
-
-uninstall-sugarPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\
- f=$(am__strip_dir) \
- rm -f "$(DESTDIR)$(sugardir)/$$f"; \
- rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \
- rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \
- done
-tags: TAGS
-TAGS:
-
-ctags: CTAGS
-CTAGS:
-
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile
-installdirs:
- for dir in "$(DESTDIR)$(sugardir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am: install-sugarPYTHON
-
-install-dvi: install-dvi-am
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-sugarPYTHON
-
-.MAKE: install-am install-strip
-
-.PHONY: all all-am check check-am clean clean-generic clean-libtool \
- distclean distclean-generic distclean-libtool distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- install-sugarPYTHON installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- uninstall uninstall-am uninstall-sugarPYTHON
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/sugar-toolkit/src/sugar/presence/__init__.py b/sugar-toolkit/src/sugar/presence/__init__.py
deleted file mode 100644
index 1136c19..0000000
--- a/sugar-toolkit/src/sugar/presence/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2006-2007, Red Hat, Inc.
-#
-# This library 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 of the License, or (at your option) any later version.
-#
-# This library 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 library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-"""Client-code's interface to the PresenceService
-
-Provides a simplified API for accessing the dbus service
-which coordinates native network presence and sharing
-information. This includes both "buddies" and "shared
-activities".
-"""
diff --git a/sugar-toolkit/src/sugar/presence/activity.py b/sugar-toolkit/src/sugar/presence/activity.py
deleted file mode 100644
index dc02aa1..0000000
--- a/sugar-toolkit/src/sugar/presence/activity.py
+++ /dev/null
@@ -1,410 +0,0 @@
-# Copyright (C) 2007, Red Hat, Inc.
-#
-# This library 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 of the License, or (at your option) any later version.
-#
-# This library 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 library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-"""UI interface to an activity in the presence service
-
-STABLE.
-"""
-
-import logging
-
-import dbus
-import gobject
-import telepathy
-
-_logger = logging.getLogger('sugar.presence.activity')
-
-class Activity(gobject.GObject):
- """UI interface for an Activity in the presence service
-
- Activities in the presence service represent your and other user's
- shared activities.
-
- Properties:
- id
- color
- name
- type
- joined
- """
- __gsignals__ = {
- 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- }
-
- __gproperties__ = {
- 'id' : (str, None, None, None, gobject.PARAM_READABLE),
- 'name' : (str, None, None, None, gobject.PARAM_READWRITE),
- 'tags' : (str, None, None, None, gobject.PARAM_READWRITE),
- 'color' : (str, None, None, None, gobject.PARAM_READWRITE),
- 'type' : (str, None, None, None, gobject.PARAM_READABLE),
- 'private' : (bool, None, None, True, gobject.PARAM_READWRITE),
- 'joined' : (bool, None, None, False, gobject.PARAM_READABLE),
- }
-
- _PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
- _ACTIVITY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Activity"
-
- def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
- """Initialse the activity interface, connecting to service"""
- gobject.GObject.__init__(self)
- self._telepathy_room_handle = None
- self._object_path = object_path
- self._ps_new_object = new_obj_cb
- self._ps_del_object = del_obj_cb
- bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
- self._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE)
- self._activity.connect_to_signal('BuddyHandleJoined',
- self._buddy_handle_joined_cb)
- self._activity.connect_to_signal('BuddyLeft',
- self._buddy_left_cb)
- self._activity.connect_to_signal('NewChannel', self._new_channel_cb)
- self._activity.connect_to_signal('PropertiesChanged',
- self._properties_changed_cb,
- utf8_strings=True)
- # FIXME: this *would* just use a normal proxy call, but I want the
- # pending call object so I can block on it, and normal proxy methods
- # don't return those as of dbus-python 0.82.1; so do it the hard way
- self._get_properties_call = bus.call_async(self._PRESENCE_SERVICE,
- object_path, self._ACTIVITY_DBUS_INTERFACE, 'GetProperties',
- '', (), self._get_properties_reply_cb,
- self._get_properties_error_cb, utf8_strings=True)
-
- self._id = None
- self._color = None
- self._name = None
- self._type = None
- self._tags = None
- self._private = True
- self._joined = False
- # Cache for get_buddy_by_handle, maps handles to buddy object paths
- self._handle_to_buddy_path = {}
- self._buddy_path_to_handle = {}
-
- # Set up by set_up_tubes()
- self.telepathy_conn = None
- self.telepathy_tubes_chan = None
- self.telepathy_text_chan = None
- self._telepathy_room = None
-
- def __repr__(self):
- return ('<proxy for %s at %x>' % (self._object_path, id(self)))
-
- def _get_properties_reply_cb(self, new_props):
- self._get_properties_call = None
- _logger.debug('%r: initial GetProperties returned', self)
- self._properties_changed_cb(new_props)
-
- def _get_properties_error_cb(self, e):
- self._get_properties_call = None
- # FIXME: do something with the error
- _logger.warning('%r: Error doing initial GetProperties: %s', self, e)
-
- def _properties_changed_cb(self, new_props):
- _logger.debug('%r: Activity properties changed to %r', self, new_props)
- val = new_props.get('name', self._name)
- if isinstance(val, str) and val != self._name:
- self._name = val
- self.notify('name')
- val = new_props.get('tags', self._tags)
- if isinstance(val, str) and val != self._tags:
- self._tags = val
- self.notify('tags')
- val = new_props.get('color', self._color)
- if isinstance(val, str) and val != self._color:
- self._color = val
- self.notify('color')
- val = bool(new_props.get('private', self._private))
- if val != self._private:
- self._private = val
- self.notify('private')
- val = new_props.get('id', self._id)
- if isinstance(val, str) and self._id is None:
- self._id = val
- self.notify('id')
- val = new_props.get('type', self._type)
- if isinstance(val, str) and self._type is None:
- self._type = val
- self.notify('type')
-
- def object_path(self):
- """Get our dbus object path"""
- return self._object_path
-
- def do_get_property(self, pspec):
- """Retrieve a particular property from our property dictionary"""
-
- if pspec.name == "joined":
- return self._joined
-
- if self._get_properties_call is not None:
- _logger.debug('%r: Blocking on GetProperties() because someone '
- 'wants property %s', self, pspec.name)
- self._get_properties_call.block()
-
- if pspec.name == "id":
- return self._id
- elif pspec.name == "name":
- return self._name
- elif pspec.name == "color":
- return self._color
- elif pspec.name == "type":
- return self._type
- elif pspec.name == "tags":
- return self._tags
- elif pspec.name == "private":
- return self._private
-
- # FIXME: need an asynchronous API to set these properties, particularly
- # 'private'
- def do_set_property(self, pspec, val):
- """Set a particular property in our property dictionary"""
- if pspec.name == "name":
- self._activity.SetProperties({'name': val})
- self._name = val
- elif pspec.name == "color":
- self._activity.SetProperties({'color': val})
- self._color = val
- elif pspec.name == "tags":
- self._activity.SetProperties({'tags': val})
- self._tags = val
- elif pspec.name == "private":
- self._activity.SetProperties({'private': val})
- self._private = val
-
- def set_private(self, val, reply_handler, error_handler):
- self._activity.SetProperties({'private': bool(val)},
- reply_handler=reply_handler,
- error_handler=error_handler)
-
- def _emit_buddy_joined_signal(self, object_path):
- """Generate buddy-joined GObject signal with presence Buddy object"""
- self.emit('buddy-joined', self._ps_new_object(object_path))
- return False
-
- def _buddy_handle_joined_cb(self, object_path, handle):
- _logger.debug('%r: buddy %s joined with handle %u', self, object_path,
- handle)
- gobject.idle_add(self._emit_buddy_joined_signal, object_path)
- self._handle_to_buddy_path[handle] = object_path
- self._buddy_path_to_handle[object_path] = handle
-
- def _emit_buddy_left_signal(self, object_path):
- """Generate buddy-left GObject signal with presence Buddy object
-
- XXX note use of _ps_new_object instead of _ps_del_object here
- """
- self.emit('buddy-left', self._ps_new_object(object_path))
- return False
-
- def _buddy_left_cb(self, object_path):
- _logger.debug('%r: buddy %s left', self, object_path)
- gobject.idle_add(self._emit_buddy_left_signal, object_path)
- handle = self._buddy_path_to_handle.pop(object_path, None)
- if handle:
- self._handle_to_buddy_path.pop(handle, None)
-
- def _emit_new_channel_signal(self, object_path):
- """Generate new-channel GObject signal with channel object path
-
- New telepathy-python communications channel has been opened
- """
- self.emit('new-channel', object_path)
- return False
-
- def _new_channel_cb(self, object_path):
- _logger.debug('%r: new channel created at %s', self, object_path)
- gobject.idle_add(self._emit_new_channel_signal, object_path)
-
- def get_joined_buddies(self):
- """Retrieve the set of Buddy objects attached to this activity
-
- returns list of presence Buddy objects that we can successfully
- create from the buddy object paths that PS has for this activity.
- """
- resp = self._activity.GetJoinedBuddies()
- buddies = []
- for item in resp:
- try:
- buddies.append(self._ps_new_object(item))
- except dbus.DBusException:
- _logger.debug(
- 'get_joined_buddies failed to get buddy object for %r',
- item)
- return buddies
-
- def get_buddy_by_handle(self, handle):
- """Retrieve the Buddy object given a telepathy handle.
-
- buddy object paths are cached in self._handle_to_buddy_path,
- so we can get the buddy without calling PS.
- """
- object_path = self._handle_to_buddy_path.get(handle, None)
- if object_path:
- buddy = self._ps_new_object(object_path)
- return buddy
- return None
-
- def invite(self, buddy, message, response_cb):
- """Invite the given buddy to join this activity.
-
- The callback will be called with one parameter: None on success,
- or an exception on failure.
- """
- op = buddy.object_path()
- _logger.debug('%r: inviting %s', self, op)
- self._activity.Invite(op, message,
- reply_handler=lambda: response_cb(None),
- error_handler=response_cb)
-
- # Joining and sharing (FIXME: sharing is actually done elsewhere)
-
- def set_up_tubes(self, reply_handler, error_handler):
-
- chans = []
-
- def tubes_ready():
- if self.telepathy_text_chan is None or \
- self.telepathy_tubes_chan is None:
- return
-
- _logger.debug('%r: finished setting up tubes', self)
- reply_handler()
-
- def tubes_chan_ready(chan):
- _logger.debug('%r: Tubes channel %r is ready', self, chan)
- self.telepathy_tubes_chan = chan
- tubes_ready()
-
- def text_chan_ready(chan):
- _logger.debug('%r: Text channel %r is ready', self, chan)
- self.telepathy_text_chan = chan
- tubes_ready()
-
- def conn_ready(conn):
- _logger.debug('%r: Connection %r is ready', self, conn)
- self.telepathy_conn = conn
- found_text_channel = False
- found_tubes_channel = False
-
- for chan_path, chan_iface, handle_type, handle_ in chans:
- if handle_type != telepathy.HANDLE_TYPE_ROOM:
- return
-
- if chan_iface == telepathy.CHANNEL_TYPE_TEXT:
- telepathy.client.Channel(
- conn.service_name, chan_path,
- ready_handler=text_chan_ready,
- error_handler=error_handler)
- found_text_channel = True
-
- elif chan_iface == telepathy.CHANNEL_TYPE_TUBES:
- telepathy.client.Channel(
- conn.service_name, chan_path,
- ready_handler=tubes_chan_ready,
- error_handler=error_handler)
- found_tubes_channel = True
-
- if not found_text_channel:
- error_handler(AssertionError("Presence Service didn't create "
- "a chatroom"))
- elif not found_tubes_channel:
- error_handler(AssertionError("Presence Service didn't create "
- "tubes channel"))
-
- def channels_listed(bus_name, conn_path, channels):
- _logger.debug('%r: Connection on %s at %s, channels: %r',
- self, bus_name, conn_path, channels)
-
- # can't use assignment for this due to Python scoping
- chans.extend(channels)
-
- telepathy.client.Connection(bus_name, conn_path,
- ready_handler=conn_ready,
- error_handler=error_handler)
-
-
- self._activity.ListChannels(reply_handler=channels_listed,
- error_handler=error_handler)
-
- def _join_cb(self):
- _logger.debug('%r: Join finished', self)
- self._joined = True
- self.emit("joined", True, None)
-
- def _join_error_cb(self, err):
- _logger.debug('%r: Join failed because: %s', self, err)
- self.emit("joined", False, str(err))
-
- def join(self):
- """Join this activity.
-
- Emits 'joined' and otherwise does nothing if we're already joined.
- """
- if self._joined:
- self.emit("joined", True, None)
- return
-
- _logger.debug('%r: joining', self)
-
- def joined():
- self.set_up_tubes(reply_handler=self._join_cb,
- error_handler=self._join_error_cb)
-
- self._activity.Join(reply_handler=joined,
- error_handler=self._join_error_cb)
-
- # GetChannels() wrapper
-
- def get_channels(self):
- """Retrieve communications channel descriptions for the activity
-
- Returns a tuple containing:
- - the D-Bus well-known service name of the connection
- (FIXME: this is redundant; in Telepathy it can be derived
- from that of the connection)
- - the D-Bus object path of the connection
- - a list of D-Bus object paths representing the channels
- associated with this activity
- """
- (bus_name, connection, channels) = self._activity.GetChannels()
- _logger.debug('%r: bus name is %s, connection is %s, channels are %r',
- self, bus_name, connection, channels)
- return bus_name, connection, channels
-
- # Leaving
-
- def _leave_cb(self):
- """Callback for async action of leaving shared activity."""
- self.emit("joined", False, "left activity")
-
- def _leave_error_cb(self, err):
- """Callback for error in async leaving of shared activity."""
- _logger.debug('Failed to leave activity: %s', err)
-
- def leave(self):
- """Leave this shared activity"""
- _logger.debug('%r: leaving', self)
- self._joined = False
- self._activity.Leave(reply_handler=self._leave_cb,
- error_handler=self._leave_error_cb)
diff --git a/sugar-toolkit/src/sugar/presence/buddy.py b/sugar-toolkit/src/sugar/presence/buddy.py
deleted file mode 100644
index fab23d2..0000000
--- a/sugar-toolkit/src/sugar/presence/buddy.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# Copyright (C) 2007, Red Hat, Inc.
-#
-# This library 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 of the License, or (at your option) any later version.
-#
-# This library 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 library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-"""UI interface to a buddy in the presence service
-
-STABLE.
-"""
-
-import gobject
-import gtk
-import dbus
-
-class Buddy(gobject.GObject):
- """UI interface for a Buddy in the presence service
-
- Each buddy interface tracks a set of activities and properties
- that can be queried to provide UI controls for manipulating
- the presence interface.
-
- Properties Dictionary:
- 'key': public key,
- 'nick': nickname ,
- 'color': color (XXX what format),
- 'current-activity': (XXX dbus path?),
- 'owner': (XXX dbus path?),
- 'icon': (XXX pixel data for an icon?)
- See __gproperties__
- """
- __gsignals__ = {
- 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([])),
- 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- }
-
- __gproperties__ = {
- 'key' : (str, None, None, None, gobject.PARAM_READABLE),
- 'icon' : (str, None, None, None, gobject.PARAM_READABLE),
- 'nick' : (str, None, None, None, gobject.PARAM_READABLE),
- 'color' : (str, None, None, None, gobject.PARAM_READABLE),
- 'current-activity' : (object, None, None, gobject.PARAM_READABLE),
- 'owner' : (bool, None, None, False, gobject.PARAM_READABLE),
- 'ip4-address' : (str, None, None, None, gobject.PARAM_READABLE)
- }
-
- _PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
- _BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy"
-
- def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
- """Initialise the reference to the buddy
-
- bus -- dbus bus object
- new_obj_cb -- callback to call when this buddy joins an activity
- del_obj_cb -- callback to call when this buddy leaves an activity
- object_path -- path to the buddy object
- """
- gobject.GObject.__init__(self)
- self._object_path = object_path
- self._ps_new_object = new_obj_cb
- self._ps_del_object = del_obj_cb
- self._properties = {}
- self._activities = {}
-
- bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
- self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE)
-
- self._icon_changed_signal = self._buddy.connect_to_signal(
- 'IconChanged', self._icon_changed_cb, byte_arrays=True)
- self._joined_activity_signal = self._buddy.connect_to_signal(
- 'JoinedActivity', self._joined_activity_cb)
- self._left_activity_signal = self._buddy.connect_to_signal(
- 'LeftActivity', self._left_activity_cb)
- self._property_changed_signal = self._buddy.connect_to_signal(
- 'PropertyChanged', self._property_changed_cb)
-
- self._properties = self._get_properties_helper()
-
- activities = self._buddy.GetJoinedActivities()
- for op in activities:
- self._activities[op] = self._ps_new_object(op)
- self._icon = None
-
- def destroy(self):
- self._icon_changed_signal.remove()
- self._joined_activity_signal.remove()
- self._left_activity_signal.remove()
- self._property_changed_signal.remove()
-
- def _get_properties_helper(self):
- """Retrieve the Buddy's property dictionary from the service object
- """
- props = self._buddy.GetProperties(byte_arrays=True)
- if not props:
- return {}
- return props
-
- def do_get_property(self, pspec):
- """Retrieve a particular property from our property dictionary
-
- pspec -- XXX some sort of GTK specifier object with attributes
- including 'name', 'active' and 'icon-name'
- """
- if pspec.name == "key":
- return self._properties["key"]
- elif pspec.name == "nick":
- return self._properties["nick"]
- elif pspec.name == "color":
- return self._properties["color"]
- elif pspec.name == "current-activity":
- if not self._properties.has_key("current-activity"):
- return None
- curact = self._properties["current-activity"]
- if not len(curact):
- return None
- for activity in self._activities.values():
- if activity.props.id == curact:
- return activity
- return None
- elif pspec.name == "owner":
- return self._properties["owner"]
- elif pspec.name == "icon":
- if not self._icon:
- self._icon = str(self._buddy.GetIcon(byte_arrays=True))
- return self._icon
- elif pspec.name == "ip4-address":
- # IPv4 address will go away quite soon
- if not self._properties.has_key("ip4-address"):
- return None
- return self._properties["ip4-address"]
-
- def object_path(self):
- """Retrieve our dbus object path"""
- return self._object_path
-
- def _emit_icon_changed_signal(self, bytes):
- """Emit GObject signal when icon has changed"""
- self._icon = str(bytes)
- self.emit('icon-changed')
- return False
-
- def _icon_changed_cb(self, icon_data):
- """Handle dbus signal by emitting a GObject signal"""
- gobject.idle_add(self._emit_icon_changed_signal, icon_data)
-
- def _emit_joined_activity_signal(self, object_path):
- """Emit activity joined signal with Activity object"""
- self.emit('joined-activity', self._ps_new_object(object_path))
- return False
-
- def _joined_activity_cb(self, object_path):
- """Handle dbus signal by emitting a GObject signal
-
- Stores the activity in activities dictionary as well
- """
- if not self._activities.has_key(object_path):
- self._activities[object_path] = self._ps_new_object(object_path)
- gobject.idle_add(self._emit_joined_activity_signal, object_path)
-
- def _emit_left_activity_signal(self, object_path):
- """Emit activity left signal with Activity object
-
- XXX this calls self._ps_new_object instead of self._ps_del_object,
- which would seem to be the incorrect callback?
- """
- self.emit('left-activity', self._ps_new_object(object_path))
- return False
-
- def _left_activity_cb(self, object_path):
- """Handle dbus signal by emitting a GObject signal
-
- Also removes from the activities dictionary
- """
- if self._activities.has_key(object_path):
- del self._activities[object_path]
- gobject.idle_add(self._emit_left_activity_signal, object_path)
-
- def _handle_property_changed_signal(self, prop_list):
- """Emit property-changed signal with property dictionary
-
- Generates a property-changed signal with the results of
- _get_properties_helper()
- """
- self._properties = self._get_properties_helper()
- # FIXME: don't leak unexposed property names
- self.emit('property-changed', prop_list)
- return False
-
- def _property_changed_cb(self, prop_list):
- """Handle dbus signal by emitting a GObject signal"""
- gobject.idle_add(self._handle_property_changed_signal, prop_list)
-
- def get_icon_pixbuf(self):
- """Retrieve Buddy's icon as a GTK pixel buffer
-
- XXX Why aren't the icons coming in as SVG?
- """
- if self.props.icon and len(self.props.icon):
- pbl = gtk.gdk.PixbufLoader()
- pbl.write(self.props.icon)
- pbl.close()
- return pbl.get_pixbuf()
- else:
- return None
-
- def get_joined_activities(self):
- """Retrieve the set of all activities which this buddy has joined
-
- Uses the GetJoinedActivities method on the service
- object to produce object paths, wraps each in an
- Activity object.
-
- returns list of presence Activity objects
- """
- try:
- resp = self._buddy.GetJoinedActivities()
- except dbus.exceptions.DBusException:
- return []
- acts = []
- for item in resp:
- acts.append(self._ps_new_object(item))
- return acts
diff --git a/sugar-toolkit/src/sugar/presence/presenceservice.py b/sugar-toolkit/src/sugar/presence/presenceservice.py
deleted file mode 100644
index a7fd1a4..0000000
--- a/sugar-toolkit/src/sugar/presence/presenceservice.py
+++ /dev/null
@@ -1,609 +0,0 @@
-# Copyright (C) 2007, Red Hat, Inc.
-#
-# This library 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 of the License, or (at your option) any later version.
-#
-# This library 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 library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-"""UI class to access system-level presence object
-
-STABLE.
-"""
-
-import logging
-import traceback
-
-import dbus
-import dbus.exceptions
-import dbus.glib
-import gobject
-
-from sugar.presence.buddy import Buddy
-from sugar.presence.activity import Activity
-
-
-DBUS_SERVICE = "org.laptop.Sugar.Presence"
-DBUS_INTERFACE = "org.laptop.Sugar.Presence"
-DBUS_PATH = "/org/laptop/Sugar/Presence"
-
-_logger = logging.getLogger('sugar.presence.presenceservice')
-
-
-class PresenceService(gobject.GObject):
- """UI-side interface to the dbus presence service
-
- This class provides UI programmers with simplified access
- to the dbus service of the same name. It allows for observing
- various events from the presence service as GObject events,
- as well as some basic introspection queries.
- """
- __gsignals__ = {
- 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- # parameters: (activity: Activity, inviter: Buddy, message: unicode)
- 'activity-invitation': (gobject.SIGNAL_RUN_FIRST, None, ([object]*3)),
- 'private-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
- gobject.TYPE_PYOBJECT, str])),
- 'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
- gobject.TYPE_PYOBJECT]))
- }
-
- _PS_BUDDY_OP = DBUS_PATH + "/Buddies/"
- _PS_ACTIVITY_OP = DBUS_PATH + "/Activities/"
-
-
- def __init__(self, allow_offline_iface=True):
- """Initialise the service and attempt to connect to events
- """
- gobject.GObject.__init__(self)
- self._objcache = {}
- self._joined = None
-
- # Get a connection to the session bus
- self._bus = dbus.SessionBus()
- self._bus.add_signal_receiver(self._name_owner_changed_cb,
- signal_name="NameOwnerChanged",
- dbus_interface="org.freedesktop.DBus")
-
- # attempt to load the interface to the service...
- self._allow_offline_iface = allow_offline_iface
- self._get_ps()
-
- def _name_owner_changed_cb(self, name, old, new):
- if name != DBUS_SERVICE:
- return
- if (old and len(old)) and (not new and not len(new)):
- # PS went away, clear out PS dbus service wrapper
- self._ps_ = None
- elif (not old and not len(old)) and (new and len(new)):
- # PS started up
- self._get_ps()
-
- _ps_ = None
- def _get_ps(self):
- """Retrieve dbus interface to PresenceService
-
- Also registers for updates from various dbus events on the
- interface.
-
- If unable to retrieve the interface, we will temporarily
- return an _OfflineInterface object to allow the calling
- code to continue functioning as though it had accessed a
- real presence service.
-
- If successful, caches the presence service interface
- for use by other methods and returns that interface
- """
- if not self._ps_:
- try:
- # NOTE: We need to follow_name_owner_changes here
- # because we can not connect to a signal unless
- # we follow the changes or we start the service
- # before we connect. Starting the service here
- # causes a major bottleneck during startup
- ps = dbus.Interface(
- self._bus.get_object(DBUS_SERVICE,
- DBUS_PATH,
- follow_name_owner_changes=True),
- DBUS_INTERFACE
- )
- except dbus.exceptions.DBusException, err:
- _logger.error(
- """Failure retrieving %r interface from
- the D-BUS service %r %r: %s""",
- DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err
- )
- if self._allow_offline_iface:
- return _OfflineInterface()
- raise RuntimeError("Failed to connect to the presence service.")
- else:
- self._ps_ = ps
- ps.connect_to_signal('BuddyAppeared',
- self._buddy_appeared_cb)
- ps.connect_to_signal('BuddyDisappeared',
- self._buddy_disappeared_cb)
- ps.connect_to_signal('ActivityAppeared',
- self._activity_appeared_cb)
- ps.connect_to_signal('ActivityDisappeared',
- self._activity_disappeared_cb)
- ps.connect_to_signal('ActivityInvitation',
- self._activity_invitation_cb)
- ps.connect_to_signal('PrivateInvitation',
- self._private_invitation_cb)
- return self._ps_
-
- _ps = property(
- _get_ps, None, None,
- """DBUS interface to the PresenceService
- (services/presence/presenceservice)"""
- )
-
- def _new_object(self, object_path):
- """Turn new object path into (cached) Buddy/Activity instance
-
- object_path -- full dbus path of the new object, must be
- prefixed with either of _PS_BUDDY_OP or _PS_ACTIVITY_OP
-
- Note that this method is called throughout the class whenever
- the representation of the object is required, it is not only
- called when the object is first discovered. The point is to only have
- _one_ Python object for any D-Bus object represented by an object path,
- effectively wrapping the D-Bus object in a single Python GObject.
-
- returns presence Buddy or Activity representation
- """
- obj = None
- try:
- obj = self._objcache[object_path]
- _logger.debug('Reused proxy %r', obj)
- except KeyError:
- if object_path.startswith(self._PS_BUDDY_OP):
- obj = Buddy(self._bus, self._new_object,
- self._del_object, object_path)
- elif object_path.startswith(self._PS_ACTIVITY_OP):
- obj = Activity(self._bus, self._new_object,
- self._del_object, object_path)
- try:
- # Pre-fill the activity's ID
- activity_id = obj.props.id
- except dbus.exceptions.DBusException:
- logging.debug('Cannot get the activity ID')
- else:
- raise RuntimeError("Unknown object type")
- self._objcache[object_path] = obj
- _logger.debug('Created proxy %r', obj)
- return obj
-
- def _have_object(self, object_path):
- return object_path in self._objcache.keys()
-
- def _del_object(self, object_path):
- """Fully remove an object from the object cache when
- it's no longer needed.
- """
- del self._objcache[object_path]
-
- def _emit_buddy_appeared_signal(self, object_path):
- """Emit GObject event with presence.buddy.Buddy object"""
- self.emit('buddy-appeared', self._new_object(object_path))
- return False
-
- def _buddy_appeared_cb(self, op):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_buddy_appeared_signal, op)
-
- def _emit_buddy_disappeared_signal(self, object_path):
- """Emit GObject event with presence.buddy.Buddy object"""
- # Don't try to create a new object here if needed; it will probably
- # fail anyway because the object has already been destroyed in the PS
- if self._have_object(object_path):
- obj = self._objcache[object_path]
- self.emit('buddy-disappeared', obj)
-
- # We cannot maintain the object in the cache because that would keep
- # a lot of objects from being collected. That includes UI objects
- # due to signals using strong references.
- # If we want to cache some despite the memory usage increase,
- # we could use a LRU cache limited to some value.
- del self._objcache[object_path]
- obj.destroy()
-
- return False
-
- def _buddy_disappeared_cb(self, object_path):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
-
- def _emit_activity_invitation_signal(self, activity_path, buddy_path,
- message):
- """Emit GObject event with presence.activity.Activity object"""
- self.emit('activity-invitation', self._new_object(activity_path),
- self._new_object(buddy_path), unicode(message))
- return False
-
- def _activity_invitation_cb(self, activity_path, buddy_path, message):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_activity_invitation_signal, activity_path,
- buddy_path, message)
-
- def _emit_private_invitation_signal(self, bus_name, connection,
- channel, chan_type):
- """Emit GObject event with bus_name, connection and channel"""
- self.emit('private-invitation', bus_name, connection,
- channel, chan_type)
- return False
-
- def _private_invitation_cb(self, bus_name, connection, channel, chan_type):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_private_invitation_signal, bus_name,
- connection, channel, chan_type)
-
- def _emit_activity_appeared_signal(self, object_path):
- """Emit GObject event with presence.activity.Activity object"""
- self.emit('activity-appeared', self._new_object(object_path))
- return False
-
- def _activity_appeared_cb(self, object_path):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_activity_appeared_signal, object_path)
-
- def _emit_activity_disappeared_signal(self, object_path):
- """Emit GObject event with presence.activity.Activity object"""
- self.emit('activity-disappeared', self._new_object(object_path))
- return False
-
- def _activity_disappeared_cb(self, object_path):
- """Callback for dbus event (forwards to method to emit GObject event)"""
- gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
-
- def get(self, object_path):
- """Return the Buddy or Activity object corresponding to the given
- D-Bus object path.
- """
- return self._new_object(object_path)
-
- def get_activities(self):
- """Retrieve set of all activities from service
-
- returns list of Activity objects for all object paths
- the service reports exist (using GetActivities)
- """
- try:
- resp = self._ps.GetActivities()
- except dbus.exceptions.DBusException, err:
- _logger.warn(
- """Unable to retrieve activity list from presence service: %s"""
- % err
- )
- return []
- else:
- acts = []
- for item in resp:
- acts.append(self._new_object(item))
- return acts
-
- def _get_activities_cb(self, reply_handler, resp):
- acts = []
- for item in resp:
- acts.append(self._new_object(item))
-
- reply_handler(acts)
-
- def _get_activities_error_cb(self, error_handler, e):
- if error_handler:
- error_handler(e)
- else:
- _logger.warn(
- """Unable to retrieve activity-list from presence service: %s"""
- % e
- )
-
- def get_activities_async(self, reply_handler=None, error_handler=None):
- """Retrieve set of all activities from service asyncronously
- """
-
- if not reply_handler:
- logging.error('Function get_activities_async called without' \
- 'a reply handler. Can not run.')
- return
-
- self._ps.GetActivities(
- reply_handler=lambda resp: \
- self._get_activities_cb(reply_handler, resp),
- error_handler=lambda e: \
- self._get_activities_error_cb(error_handler, e))
-
-
- def get_activity(self, activity_id, warn_if_none=True):
- """Retrieve single Activity object for the given unique id
-
- activity_id -- unique ID for the activity
-
- returns single Activity object or None if the activity
- is not found using GetActivityById on the service
- """
- try:
- act_op = self._ps.GetActivityById(activity_id)
- except dbus.exceptions.DBusException, err:
- if warn_if_none:
- _logger.warn("Unable to retrieve activity handle for %r from "
- "presence service: %s", activity_id, err)
- return None
- return self._new_object(act_op)
-
- def get_buddies(self):
- """Retrieve set of all buddies from service
-
- returns list of Buddy objects for all object paths
- the service reports exist (using GetBuddies)
- """
- try:
- resp = self._ps.GetBuddies()
- except dbus.exceptions.DBusException, err:
- _logger.warn(
- """Unable to retrieve buddy-list from presence service: %s"""
- % err
- )
- return []
- else:
- buddies = []
- for item in resp:
- buddies.append(self._new_object(item))
- return buddies
-
- def _get_buddies_cb(self, reply_handler, resp):
- buddies = []
- for item in resp:
- buddies.append(self._new_object(item))
-
- reply_handler(buddies)
-
- def _get_buddies_error_cb(self, error_handler, e):
- if error_handler:
- error_handler(e)
- else:
- _logger.warn(
- """Unable to retrieve buddy-list from presence service: %s"""
- % e
- )
-
- def get_buddies_async(self, reply_handler=None, error_handler=None):
- """Retrieve set of all buddies from service asyncronously
- """
-
- if not reply_handler:
- logging.error('Function get_buddies_async called without' \
- 'a reply handler. Can not run.')
- return
-
- self._ps.GetBuddies(
- reply_handler=lambda resp: \
- self._get_buddies_cb(reply_handler, resp),
- error_handler=lambda e: \
- self._get_buddies_error_cb(error_handler, e))
-
- def get_buddy(self, key):
- """Retrieve single Buddy object for the given public key
-
- key -- buddy's public encryption key
-
- returns single Buddy object or None if the activity
- is not found using GetBuddyByPublicKey on the
- service
- """
- try:
- buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key))
- except dbus.exceptions.DBusException, err:
- _logger.warn(
- """Unable to retrieve buddy handle
- for %r from presence service: %s"""
- % key, err
- )
- return None
- return self._new_object(buddy_op)
-
- def get_buddy_by_telepathy_handle(self, tp_conn_name, tp_conn_path,
- handle):
- """Retrieve single Buddy object for the given public key
-
- :Parameters:
- `tp_conn_name` : str
- The well-known bus name of a Telepathy connection
- `tp_conn_path` : dbus.ObjectPath
- The object path of the Telepathy connection
- `handle` : int or long
- The handle of a Telepathy contact on that connection,
- of type HANDLE_TYPE_CONTACT. This may not be a
- channel-specific handle.
- :Returns: the Buddy object, or None if the buddy is not found
- """
- try:
- buddy_op = self._ps.GetBuddyByTelepathyHandle(tp_conn_name,
- tp_conn_path,
- handle)
- except dbus.exceptions.DBusException, err:
- _logger.warn('Unable to retrieve buddy handle for handle %u at '
- 'conn %s:%s from presence service: %s',
- handle, tp_conn_name, tp_conn_path, err)
- return None
- return self._new_object(buddy_op)
-
- def get_owner(self):
- """Retrieves the laptop "owner" Buddy object."""
- try:
- owner_op = self._ps.GetOwner()
- except dbus.exceptions.DBusException, err:
- _logger.warn(
- """Unable to retrieve local user/owner
- from presence service: %s"""
- % err
- )
- raise RuntimeError("Could not get owner object.")
- return self._new_object(owner_op)
-
- def _share_activity_cb(self, activity, op):
- """Finish sharing the activity
- """
- # FIXME find a better way to shutup pylint
- psact = self._new_object(op)
- psact._joined = True
- _logger.debug('%r: Just shared, setting up tubes', activity)
- psact.set_up_tubes(reply_handler=lambda:
- self.emit("activity-shared", True, psact, None),
- error_handler=lambda e:
- self._share_activity_error_cb(activity, e))
-
- def _share_activity_error_cb(self, activity, err):
- """Notify with GObject event of unsuccessful sharing of activity"""
- _logger.debug("Error sharing activity %s: %s" %
- (activity.get_id(), err))
- self.emit("activity-shared", False, None, err)
-
- def share_activity(self, activity, properties=None, private=True):
- """Ask presence service to ask the activity to share itself publicly.
-
- Uses the AdvertiseActivity method on the service to ask for the
- sharing of the given activity. Arranges to emit activity-shared
- event with:
-
- (success, Activity, err)
-
- on success/failure.
-
- returns None
- """
- actid = activity.get_id()
-
- if properties is None:
- properties = {}
-
- # Ensure the activity is not already shared/joined
- for obj in self._objcache.values():
- if not isinstance(object, Activity):
- continue
- if obj.props.id == actid or obj.props.joined:
- raise RuntimeError("Activity %s is already shared." %
- actid)
-
- atype = activity.get_bundle_id()
- name = activity.props.title
- properties['private'] = bool(private)
- self._ps.ShareActivity(actid, atype, name, properties,
- reply_handler=lambda op: \
- self._share_activity_cb(activity, op),
- error_handler=lambda e: \
- self._share_activity_error_cb(activity, e))
-
- def get_preferred_connection(self):
- """Gets the preferred telepathy connection object that an activity
- should use when talking directly to telepathy
-
- returns the bus name and the object path of the Telepathy connection"""
-
- try:
- bus_name, object_path = self._ps.GetPreferredConnection()
- except dbus.exceptions.DBusException:
- logging.error(traceback.format_exc())
- return None
-
- return bus_name, object_path
-
-class _OfflineInterface( object ):
- """Offline-presence-service interface
-
- Used to mimic the behaviour of a real PresenceService sufficiently
- to avoid crashing client code that expects the given interface.
-
- XXX we could likely return a "MockOwner" object reasonably
- easily, but would it be worth it?
- """
- def raiseException( self, *args, **named ):
- """Raise dbus.exceptions.DBusException"""
- raise dbus.exceptions.DBusException(
- """PresenceService Interface not available"""
- )
- GetActivities = raiseException
- GetActivityById = raiseException
- GetBuddies = raiseException
- GetBuddyByPublicKey = raiseException
- GetOwner = raiseException
- GetPreferredConnection = raiseException
- def ShareActivity(
- self, actid, atype, name, properties,
- reply_handler, error_handler,
- ):
- """Pretend to share and fail..."""
- exc = IOError(
- """Unable to share activity as PresenceService
- is not currenly available"""
- )
- return error_handler( exc )
-
-class _MockPresenceService(gobject.GObject):
- """Test fixture allowing testing of items that use PresenceService
-
- See PresenceService for usage and purpose
- """
- __gsignals__ = {
- 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'private-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
- gobject.TYPE_PYOBJECT])),
- 'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT]))
- }
-
- def __init__(self):
- gobject.GObject.__init__(self)
-
- def get_activities(self):
- return []
-
- def get_activity(self, activity_id):
- return None
-
- def get_buddies(self):
- return []
-
- def get_buddy(self, key):
- return None
-
- def get_owner(self):
- return None
-
- def share_activity(self, activity, properties=None):
- return None
-
-_ps = None
-def get_instance(allow_offline_iface=False):
- """Retrieve this process' view of the PresenceService"""
- global _ps
- if not _ps:
- _ps = PresenceService(allow_offline_iface)
- return _ps
-
diff --git a/sugar-toolkit/src/sugar/presence/sugartubeconn.py b/sugar-toolkit/src/sugar/presence/sugartubeconn.py
deleted file mode 100644
index 954ef67..0000000
--- a/sugar-toolkit/src/sugar/presence/sugartubeconn.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (C) 2008 One Laptop Per Child
-#
-# This program 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.
-#
-# This program 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 program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""Subclass of TubeConnection that converts handles to Sugar Buddies
-
-STABLE.
-"""
-
-from telepathy.constants import (
- CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES)
-
-from sugar.presence.tubeconn import TubeConnection
-from sugar.presence import presenceservice
-
-
-class SugarTubeConnection(TubeConnection):
- """Subclass of TubeConnection that converts handles to Sugar Buddies"""
-
- def __new__(cls, conn, tubes_iface, tube_id, address=None,
- group_iface=None, mainloop=None):
- self = super(SugarTubeConnection, cls).__new__(
- cls, conn, tubes_iface, tube_id, address=address,
- group_iface=group_iface, mainloop=mainloop)
- self._conn = conn
- self._group_iface = group_iface
- return self
-
- def get_buddy(self, cs_handle):
- """Retrieve a Buddy object given a telepathy handle.
-
- cs_handle: A channel-specific CONTACT type handle.
- returns: sugar.presence Buddy object or None
- """
- pservice = presenceservice.get_instance()
- if self.self_handle == cs_handle:
- # It's me, just get my global handle
- handle = self._conn.GetSelfHandle()
- elif self._group_iface.GetGroupFlags() & \
- CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES:
- # The group (channel) has channel specific handles
- handle = self._group_iface.GetHandleOwners([cs_handle])[0]
- else:
- # The group does not have channel specific handles
- handle = cs_handle
-
- # deal with failure to get the handle owner
- if handle == 0:
- return None
- return pservice.get_buddy_by_telepathy_handle(
- self._conn.service_name, self._conn.object_path, handle)
diff --git a/sugar-toolkit/src/sugar/presence/test_presence.txt b/sugar-toolkit/src/sugar/presence/test_presence.txt
deleted file mode 100644
index d0736a9..0000000
--- a/sugar-toolkit/src/sugar/presence/test_presence.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This is a test of presence.
-
-To test this service we will start up a mock dbus library:
-
- >>> from sugar.testing import mockdbus
- >>> import dbus
- >>> pres_service = mockdbus.MockService(
- ... 'org.laptop.Presence', '/org/laptop/Presence', name='pres')
- >>> pres_service.install()
- >>> pres_interface = dbus.Interface(pres_service, 'org.laptop.Presence')
-
-Then we import the library (second, to make sure it connects to our
-mocked system, though the lazy instantiation in get_instance() should
-handle it):
-
- >>> from sugar.presence import PresenceService
- >>> ps = PresenceService.get_instance()
- >>> pres_interface.make_response('getServices', [])
- >>> ps.get_services()
- Called pres.org.laptop.Presence:getServices()
- []
- >>> pres_interface.make_response('getBuddies', [])
- >>> ps.get_buddies()
- Called pres.org.laptop.Presence:getBuddies()
- []
-
diff --git a/sugar-toolkit/src/sugar/presence/tubeconn.py b/sugar-toolkit/src/sugar/presence/tubeconn.py
deleted file mode 100644
index 8606db6..0000000
--- a/sugar-toolkit/src/sugar/presence/tubeconn.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# This should eventually land in telepathy-python, so has the same license:
-
-# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# This program 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.
-#
-# This program 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 program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-STABLE.
-"""
-
-__all__ = ('TubeConnection',)
-__docformat__ = 'reStructuredText'
-
-
-import logging
-
-from dbus.connection import Connection
-
-
-logger = logging.getLogger('telepathy.tubeconn')
-
-
-class TubeConnection(Connection):
-
- # pylint: disable-msg=W0212
- # Confused by __new__
- def __new__(cls, conn, tubes_iface, tube_id, address=None,
- group_iface=None, mainloop=None):
- if address is None:
- address = tubes_iface.GetDBusTubeAddress(tube_id)
- self = super(TubeConnection, cls).__new__(cls, address,
- mainloop=mainloop)
-
- self._tubes_iface = tubes_iface
- self.tube_id = tube_id
- self.participants = {}
- self.bus_name_to_handle = {}
- self._mapping_watches = []
-
- if group_iface is None:
- method = conn.GetSelfHandle
- else:
- method = group_iface.GetSelfHandle
- method(reply_handler=self._on_get_self_handle_reply,
- error_handler=self._on_get_self_handle_error)
-
- return self
-
- # pylint: disable-msg=W0201
- # Confused by __new__
- def _on_get_self_handle_reply(self, handle):
- self.self_handle = handle
- match = self._tubes_iface.connect_to_signal('DBusNamesChanged',
- self._on_dbus_names_changed)
- self._tubes_iface.GetDBusNames(self.tube_id,
- reply_handler=self._on_get_dbus_names_reply,
- error_handler=self._on_get_dbus_names_error)
- self._dbus_names_changed_match = match
-
- def _on_get_self_handle_error(self, e):
- logging.basicConfig()
- logger.error('GetSelfHandle failed: %s', e)
-
- def close(self):
- self._dbus_names_changed_match.remove()
- self._on_dbus_names_changed(self.tube_id, (), self.participants.keys())
- super(TubeConnection, self).close()
-
- def _on_get_dbus_names_reply(self, names):
- self._on_dbus_names_changed(self.tube_id, names, ())
-
- def _on_get_dbus_names_error(self, e):
- logging.basicConfig()
- logger.error('GetDBusNames failed: %s', e)
-
- def _on_dbus_names_changed(self, tube_id, added, removed):
- if tube_id == self.tube_id:
- for handle, bus_name in added:
- if handle == self.self_handle:
- # I've just joined - set my unique name
- self.set_unique_name(bus_name)
- self.participants[handle] = bus_name
- self.bus_name_to_handle[bus_name] = handle
-
- # call the callback while the removed people are still in
- # participants, so their bus names are available
- for callback in self._mapping_watches:
- callback(added, removed)
-
- for handle in removed:
- bus_name = self.participants.pop(handle, None)
- self.bus_name_to_handle.pop(bus_name, None)
-
- def watch_participants(self, callback):
- self._mapping_watches.append(callback)
- if self.participants:
- # GetDBusNames already returned: fake a participant add event
- # immediately
- added = []
- for k, v in self.participants.iteritems():
- added.append((k, v))
- callback(added, [])