summaryrefslogtreecommitdiff
path: root/_dbus_bindings
diff options
context:
space:
mode:
Diffstat (limited to '_dbus_bindings')
-rw-r--r--_dbus_bindings/Makefile.am35
-rw-r--r--_dbus_bindings/Makefile.in647
-rw-r--r--_dbus_bindings/abstract.c664
-rw-r--r--_dbus_bindings/bus.c187
-rw-r--r--_dbus_bindings/bytes.c267
-rw-r--r--_dbus_bindings/conn-internal.h67
-rw-r--r--_dbus_bindings/conn-methods.c1037
-rw-r--r--_dbus_bindings/conn.c471
-rw-r--r--_dbus_bindings/containers.c769
-rw-r--r--_dbus_bindings/dbus_bindings-internal.h245
-rw-r--r--_dbus_bindings/debug.c95
-rw-r--r--_dbus_bindings/exceptions.c99
-rw-r--r--_dbus_bindings/float.c158
-rw-r--r--_dbus_bindings/generic.c84
-rw-r--r--_dbus_bindings/int.c779
-rw-r--r--_dbus_bindings/libdbusconn.c124
-rw-r--r--_dbus_bindings/mainloop.c208
-rw-r--r--_dbus_bindings/message-append.c1092
-rw-r--r--_dbus_bindings/message-get-args.c523
-rw-r--r--_dbus_bindings/message-internal.h49
-rw-r--r--_dbus_bindings/message.c1063
-rw-r--r--_dbus_bindings/module.c395
-rw-r--r--_dbus_bindings/pending-call.c293
-rw-r--r--_dbus_bindings/server.c581
-rw-r--r--_dbus_bindings/signature.c247
-rw-r--r--_dbus_bindings/string.c380
-rw-r--r--_dbus_bindings/types-internal.h95
-rw-r--r--_dbus_bindings/validation.c245
28 files changed, 10899 insertions, 0 deletions
diff --git a/_dbus_bindings/Makefile.am b/_dbus_bindings/Makefile.am
new file mode 100644
index 0000000..c6cd1ee
--- /dev/null
+++ b/_dbus_bindings/Makefile.am
@@ -0,0 +1,35 @@
+pyexec_LTLIBRARIES = _dbus_bindings.la
+
+AM_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) $(PYTHON_INCLUDES)
+AM_LDFLAGS = -module -avoid-version -export-symbols-regex init_dbus_bindings \
+ $(DBUS_LIBS)
+_dbus_bindings_la_SOURCES = \
+ abstract.c \
+ bus.c \
+ bytes.c \
+ conn.c \
+ conn-internal.h \
+ conn-methods.c \
+ containers.c \
+ dbus_bindings-internal.h \
+ debug.c \
+ exceptions.c \
+ float.c \
+ generic.c \
+ int.c \
+ libdbusconn.c \
+ mainloop.c \
+ message-append.c \
+ message.c \
+ message-get-args.c \
+ message-internal.h \
+ module.c \
+ pending-call.c \
+ server.c \
+ signature.c \
+ string.c \
+ types-internal.h \
+ validation.c
+
+check_c_sources = $(_dbus_bindings_la_SOURCES)
+include $(top_srcdir)/tools/check-coding-style.mk
diff --git a/_dbus_bindings/Makefile.in b/_dbus_bindings/Makefile.in
new file mode 100644
index 0000000..99a4b2a
--- /dev/null
+++ b/_dbus_bindings/Makefile.in
@@ -0,0 +1,647 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/tools/check-coding-style.mk
+subdir = _dbus_bindings
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/am-check-pymod.m4 \
+ $(top_srcdir)/m4/am-check-python-headers.m4 \
+ $(top_srcdir)/m4/dbus-py-add-rst2htmlflag.m4 \
+ $(top_srcdir)/m4/jh-add-cflag.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/tp-compiler-flag.m4 \
+ $(top_srcdir)/m4/tp-compiler-warnings.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pyexecdir)"
+LTLIBRARIES = $(pyexec_LTLIBRARIES)
+_dbus_bindings_la_LIBADD =
+am__dbus_bindings_la_OBJECTS = abstract.lo bus.lo bytes.lo conn.lo \
+ conn-methods.lo containers.lo debug.lo exceptions.lo float.lo \
+ generic.lo int.lo libdbusconn.lo mainloop.lo message-append.lo \
+ message.lo message-get-args.lo module.lo pending-call.lo \
+ server.lo signature.lo string.lo validation.lo
+_dbus_bindings_la_OBJECTS = $(am__dbus_bindings_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(_dbus_bindings_la_SOURCES)
+DIST_SOURCES = $(_dbus_bindings_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
+DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_PYTHON_MAJOR_VERSION = @DBUS_PYTHON_MAJOR_VERSION@
+DBUS_PYTHON_MICRO_VERSION = @DBUS_PYTHON_MICRO_VERSION@
+DBUS_PYTHON_MINOR_VERSION = @DBUS_PYTHON_MINOR_VERSION@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EPYDOC = @EPYDOC@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+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_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLATFORM = @PLATFORM@
+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@
+RST2HTML = @RST2HTML@
+RST2HTMLFLAGS = @RST2HTMLFLAGS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+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_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pyexec_LTLIBRARIES = _dbus_bindings.la
+AM_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) $(PYTHON_INCLUDES)
+AM_LDFLAGS = -module -avoid-version -export-symbols-regex init_dbus_bindings \
+ $(DBUS_LIBS)
+
+_dbus_bindings_la_SOURCES = \
+ abstract.c \
+ bus.c \
+ bytes.c \
+ conn.c \
+ conn-internal.h \
+ conn-methods.c \
+ containers.c \
+ dbus_bindings-internal.h \
+ debug.c \
+ exceptions.c \
+ float.c \
+ generic.c \
+ int.c \
+ libdbusconn.c \
+ mainloop.c \
+ message-append.c \
+ message.c \
+ message-get-args.c \
+ message-internal.h \
+ module.c \
+ pending-call.c \
+ server.c \
+ signature.c \
+ string.c \
+ types-internal.h \
+ validation.c
+
+check_c_sources = $(_dbus_bindings_la_SOURCES)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu _dbus_bindings/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu _dbus_bindings/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
+$(am__aclocal_m4_deps):
+install-pyexecLTLIBRARIES: $(pyexec_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pyexecdir)"
+ @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyexecdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyexecdir)"; \
+ }
+
+uninstall-pyexecLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyexecdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyexecdir)/$$f"; \
+ done
+
+clean-pyexecLTLIBRARIES:
+ -test -z "$(pyexec_LTLIBRARIES)" || rm -f $(pyexec_LTLIBRARIES)
+ @list='$(pyexec_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+_dbus_bindings.la: $(_dbus_bindings_la_OBJECTS) $(_dbus_bindings_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) -rpath $(pyexecdir) $(_dbus_bindings_la_OBJECTS) $(_dbus_bindings_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abstract.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-methods.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/containers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exceptions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdbusconn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainloop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message-append.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message-get-args.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pending-call.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signature.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/validation.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+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 "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pyexecdir)"; 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)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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 clean-pyexecLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pyexecLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pyexecLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
+ clean-generic clean-libtool clean-pyexecLTLIBRARIES ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags 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-pyexecLTLIBRARIES \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pyexecLTLIBRARIES
+
+check-local::
+ @fail=0; \
+ cd $(srcdir) || exit $$?; \
+ if test -n "$(check_misc_sources)"; then \
+ echo check-coding-style.mk: checking misc sources...; \
+ top_srcdir=$(top_srcdir) \
+ sh $(top_srcdir)/tools/check-whitespace.sh \
+ $(check_misc_sources) || fail=1; \
+ fi; \
+ if test -n "$(check_py_sources)"; then \
+ echo check-coding-style.mk: checking Python sources...; \
+ top_srcdir=$(top_srcdir) \
+ sh $(top_srcdir)/tools/check-py-style.sh \
+ $(check_py_sources) || fail=1; \
+ fi;\
+ if test -n "$(check_c_sources)"; then \
+ echo check-coding-style.mk: checking C sources...; \
+ top_srcdir=$(top_srcdir) \
+ sh $(top_srcdir)/tools/check-c-style.sh \
+ $(check_c_sources) || fail=1; \
+ fi;\
+ if test yes = "@ENABLE_CODING_STYLE_CHECKS@"; then \
+ exit "$$fail";\
+ else \
+ exit 0;\
+ fi
+
+# 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/_dbus_bindings/abstract.c b/_dbus_bindings/abstract.c
new file mode 100644
index 0000000..9a4f350
--- /dev/null
+++ b/_dbus_bindings/abstract.c
@@ -0,0 +1,664 @@
+/* Subclasses of built-in Python types supporting extra D-Bus functionality.
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+#include "types-internal.h"
+
+/* Dict indexed by object IDs, whose values are nonzero variant levels
+ * for immutable variable-sized D-Bus data types (_LongBase, _StrBase, Struct).
+ *
+ * This is a strange way to store them, but adding a __dict__ to the offending
+ * objects seems even more error-prone, given that their sizes are variable!
+ */
+PyObject *_dbus_py_variant_levels = NULL;
+
+long
+dbus_py_variant_level_get(PyObject *obj)
+{
+ PyObject *vl_obj;
+ PyObject *key = PyLong_FromVoidPtr(obj);
+
+ if (!key) {
+ return 0;
+ }
+
+ vl_obj = PyDict_GetItem(_dbus_py_variant_levels, key);
+ Py_DECREF(key);
+
+ if (!vl_obj)
+ return 0;
+ return PyInt_AsLong(vl_obj);
+}
+
+dbus_bool_t
+dbus_py_variant_level_set(PyObject *obj, long variant_level)
+{
+ /* key is the object's ID (= pointer) to avoid referencing it */
+ PyObject *key = PyLong_FromVoidPtr(obj);
+
+ if (!key) {
+ return FALSE;
+ }
+
+ if (variant_level <= 0) {
+ if (PyDict_GetItem (_dbus_py_variant_levels, key)) {
+ if (PyDict_DelItem (_dbus_py_variant_levels, key) < 0) {
+ Py_DECREF(key);
+ return FALSE;
+ }
+ }
+ }
+ else {
+ PyObject *vl_obj = PyInt_FromLong(variant_level);
+ if (!vl_obj) {
+ Py_DECREF(key);
+ return FALSE;
+ }
+ if (PyDict_SetItem (_dbus_py_variant_levels, key, vl_obj) < 0) {
+ Py_DECREF(key);
+ return FALSE;
+ }
+ }
+ Py_DECREF(key);
+ return TRUE;
+}
+
+PyObject *
+dbus_py_variant_level_getattro(PyObject *obj, PyObject *name)
+{
+ PyObject *key, *value;
+
+ if (PyString_Check(name)) {
+ Py_INCREF(name);
+ }
+ else if (PyUnicode_Check(name)) {
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);
+ if (!name) {
+ return NULL;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "attribute name must be string");
+ return NULL;
+ }
+
+ if (strcmp(PyString_AS_STRING(name), "variant_level")) {
+ value = PyObject_GenericGetAttr(obj, name);
+ Py_DECREF(name);
+ return value;
+ }
+
+ Py_DECREF(name);
+
+ key = PyLong_FromVoidPtr(obj);
+
+ if (!key) {
+ return NULL;
+ }
+
+ value = PyDict_GetItem(_dbus_py_variant_levels, key);
+ Py_DECREF(key);
+
+ if (!value)
+ return PyInt_FromLong(0);
+ Py_INCREF(value);
+ return value;
+}
+
+/* To be invoked by destructors. Clear the variant level without touching the
+ * exception state */
+void
+dbus_py_variant_level_clear(PyObject *self)
+{
+ PyObject *et, *ev, *etb;
+
+ /* avoid clobbering any pending exception */
+ PyErr_Fetch(&et, &ev, &etb);
+ if (!dbus_py_variant_level_set(self, 0)) {
+ /* should never happen */
+ PyErr_WriteUnraisable(self);
+ }
+ PyErr_Restore(et, ev, etb);
+}
+
+/* Support code for int subclasses. ================================== */
+
+PyDoc_STRVAR(DBusPythonInt_tp_doc,\
+"Base class for int subclasses with a ``variant_level`` attribute.\n"
+"Do not rely on the existence of this class outside dbus-python.\n"
+);
+
+static PyMemberDef DBusPythonInt_tp_members[] = {
+ {"variant_level", T_LONG, offsetof(DBusPyIntBase, variant_level),
+ READONLY,
+ "The number of nested variants wrapping the real data. "
+ "0 if not in a variant."},
+ {NULL},
+};
+
+static PyObject *
+DBusPythonInt_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes at most one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ self = (PyInt_Type.tp_new)(cls, args, NULL);
+ if (self) {
+ ((DBusPyIntBase *)self)->variant_level = variantness;
+ }
+ return self;
+}
+
+static PyObject *
+DBusPythonInt_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyInt_Type.tp_repr)(self);
+ long variant_level = ((DBusPyIntBase *)self)->variant_level;
+ PyObject *my_repr;
+
+ if (!parent_repr) return NULL;
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr));
+ }
+ /* whether my_repr is NULL or not: */
+ Py_DECREF(parent_repr);
+ return my_repr;
+}
+
+PyTypeObject DBusPyIntBase_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "_dbus_bindings._IntBase",
+ sizeof(DBusPyIntBase),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ DBusPythonInt_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DBusPythonInt_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ DBusPythonInt_tp_members, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ PyType_GenericAlloc, /* tp_alloc */
+ DBusPythonInt_tp_new, /* tp_new */
+ PyObject_Del, /* tp_free */
+};
+
+/* Support code for float subclasses. ================================ */
+
+/* There's only one subclass at the moment (Double) but these are factored
+out to make room for Float later. (Float is implemented and #if'd out) */
+
+PyDoc_STRVAR(DBusPythonFloat_tp_doc,\
+"Base class for float subclasses with a ``variant_level`` attribute.\n"
+"Do not rely on the existence of this class outside dbus-python.\n"
+);
+
+static PyMemberDef DBusPythonFloat_tp_members[] = {
+ {"variant_level", T_LONG, offsetof(DBusPyFloatBase, variant_level),
+ READONLY,
+ "The number of nested variants wrapping the real data. "
+ "0 if not in a variant."},
+ {NULL},
+};
+
+static PyObject *
+DBusPythonFloat_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes at most one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ self = (PyFloat_Type.tp_new)(cls, args, NULL);
+ if (self) {
+ ((DBusPyFloatBase *)self)->variant_level = variantness;
+ }
+ return self;
+}
+
+static PyObject *
+DBusPythonFloat_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyFloat_Type.tp_repr)(self);
+ long variant_level = ((DBusPyFloatBase *)self)->variant_level;
+ PyObject *my_repr;
+
+ if (!parent_repr) return NULL;
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr));
+ }
+ /* whether my_repr is NULL or not: */
+ Py_DECREF(parent_repr);
+ return my_repr;
+}
+
+PyTypeObject DBusPyFloatBase_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "_dbus_bindings._FloatBase",
+ sizeof(DBusPyFloatBase),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ DBusPythonFloat_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DBusPythonFloat_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ DBusPythonFloat_tp_members, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyFloat_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ DBusPythonFloat_tp_new, /* tp_new */
+};
+
+/* Support code for str subclasses ================================== */
+
+PyDoc_STRVAR(DBusPythonString_tp_doc,\
+"Base class for str subclasses with a ``variant_level`` attribute.\n"
+"Do not rely on the existence of this class outside dbus-python.\n"
+);
+
+static PyObject *
+DBusPythonString_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes at most one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ self = (PyString_Type.tp_new)(cls, args, NULL);
+ if (self) {
+ if (!dbus_py_variant_level_set(self, variantness)) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return self;
+}
+
+static PyObject *
+DBusPythonString_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyString_Type.tp_repr)(self);
+ PyObject *vl_obj;
+ PyObject *my_repr;
+ long variant_level;
+
+ if (!parent_repr) return NULL;
+ vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
+ if (!vl_obj) {
+ Py_DECREF(parent_repr);
+ return NULL;
+ }
+ variant_level = PyInt_AsLong(vl_obj);
+ Py_DECREF(vl_obj);
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr));
+ }
+ /* whether my_repr is NULL or not: */
+ Py_DECREF(parent_repr);
+ return my_repr;
+}
+
+static void
+DBusPyStrBase_tp_dealloc(PyObject *self)
+{
+ dbus_py_variant_level_clear(self);
+ (PyString_Type.tp_dealloc)(self);
+}
+
+PyTypeObject DBusPyStrBase_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "_dbus_bindings._StrBase",
+ 0,
+ 0,
+ DBusPyStrBase_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ DBusPythonString_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ dbus_py_variant_level_getattro, /* tp_getattro */
+ dbus_py_immutable_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DBusPythonString_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyString_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ DBusPythonString_tp_new, /* tp_new */
+};
+
+/* Support code for long subclasses ================================= */
+
+PyDoc_STRVAR(DBusPythonLong_tp_doc,\
+"Base class for ``long`` subclasses with a ``variant_level`` attribute.\n"
+"Do not rely on the existence of this class outside dbus-python.\n"
+);
+
+static PyObject *
+DBusPythonLong_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes at most one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ self = (PyLong_Type.tp_new)(cls, args, NULL);
+ if (self) {
+ if (!dbus_py_variant_level_set(self, variantness)) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return self;
+}
+
+static PyObject *
+DBusPythonLong_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyLong_Type.tp_repr)(self);
+ PyObject *vl_obj;
+ PyObject *my_repr;
+ long variant_level;
+
+ if (!parent_repr) return NULL;
+ vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
+ if (!vl_obj) {
+ Py_DECREF(parent_repr);
+ return NULL;
+ }
+ variant_level = PyInt_AsLong(vl_obj);
+ Py_DECREF(vl_obj);
+ if (variant_level) {
+ my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr));
+ }
+ /* whether my_repr is NULL or not: */
+ Py_DECREF(parent_repr);
+ return my_repr;
+}
+
+static void
+DBusPyLongBase_tp_dealloc(PyObject *self)
+{
+ dbus_py_variant_level_clear(self);
+ (PyLong_Type.tp_dealloc)(self);
+}
+
+PyTypeObject DBusPyLongBase_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "_dbus_bindings._LongBase",
+ 0,
+ 0,
+ DBusPyLongBase_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ DBusPythonLong_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ dbus_py_variant_level_getattro, /* tp_getattro */
+ dbus_py_immutable_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DBusPythonLong_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyLong_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ DBusPythonLong_tp_new, /* tp_new */
+};
+
+PyObject *dbus_py_variant_level_const = NULL;
+PyObject *dbus_py_signature_const = NULL;
+PyObject *dbus_py__dbus_object_path__const = NULL;
+
+dbus_bool_t
+dbus_py_init_abstract(void)
+{
+ _dbus_py_variant_levels = PyDict_New();
+ if (!_dbus_py_variant_levels) return 0;
+
+ dbus_py__dbus_object_path__const = PyString_InternFromString("__dbus_object_path__");
+ if (!dbus_py__dbus_object_path__const) return 0;
+
+ dbus_py_variant_level_const = PyString_InternFromString("variant_level");
+ if (!dbus_py_variant_level_const) return 0;
+
+ dbus_py_signature_const = PyString_InternFromString("signature");
+ if (!dbus_py_signature_const) return 0;
+
+ DBusPyIntBase_Type.tp_base = &PyInt_Type;
+ if (PyType_Ready(&DBusPyIntBase_Type) < 0) return 0;
+ /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
+ desired */
+ DBusPyIntBase_Type.tp_print = NULL;
+
+ DBusPyFloatBase_Type.tp_base = &PyFloat_Type;
+ if (PyType_Ready(&DBusPyFloatBase_Type) < 0) return 0;
+ DBusPyFloatBase_Type.tp_print = NULL;
+
+ DBusPyLongBase_Type.tp_base = &PyLong_Type;
+ if (PyType_Ready(&DBusPyLongBase_Type) < 0) return 0;
+ DBusPyLongBase_Type.tp_print = NULL;
+
+ DBusPyStrBase_Type.tp_base = &PyString_Type;
+ if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0;
+ DBusPyStrBase_Type.tp_print = NULL;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_abstract_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyIntBase_Type);
+ Py_INCREF(&DBusPyLongBase_Type);
+ Py_INCREF(&DBusPyStrBase_Type);
+ Py_INCREF(&DBusPyFloatBase_Type);
+ if (PyModule_AddObject(this_module, "_IntBase",
+ (PyObject *)&DBusPyIntBase_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "_LongBase",
+ (PyObject *)&DBusPyLongBase_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "_StrBase",
+ (PyObject *)&DBusPyStrBase_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "_FloatBase",
+ (PyObject *)&DBusPyFloatBase_Type) < 0) return 0;
+
+ return 1;
+}
diff --git a/_dbus_bindings/bus.c b/_dbus_bindings/bus.c
new file mode 100644
index 0000000..7ab0d95
--- /dev/null
+++ b/_dbus_bindings/bus.c
@@ -0,0 +1,187 @@
+/* Implementation of Bus, a subtype of Connection.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include "conn-internal.h"
+
+PyObject *
+DBusPyConnection_NewForBus(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *first = NULL, *mainloop = NULL;
+ DBusConnection *conn;
+ DBusError error;
+ Connection *self;
+ static char *argnames[] = {"address_or_type", "mainloop", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", argnames,
+ &first, &mainloop)) {
+ return NULL;
+ }
+
+ dbus_error_init(&error);
+
+ if (first && PyString_Check(first)) {
+ dbus_bool_t ret;
+
+ /* It's a custom address. First connect to it, then register. */
+
+ self = (Connection *)(DBusPyConnection_Type.tp_new)(cls, args, kwargs);
+ if (!self) return NULL;
+ TRACE(self);
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_bus_register(self->conn, &error);
+ Py_END_ALLOW_THREADS
+ if (!ret) {
+ DBusPyException_ConsumeError(&error);
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ return (PyObject *)self;
+ }
+ else if (!first || PyInt_Check(first)) {
+ long type;
+ PyObject *libdbusconn;
+ PyObject *new_args;
+ PyObject *new_kwargs;
+
+ /* If the first argument isn't a string, it must be an integer
+ representing one of the well-known bus types. The default is
+ DBUS_BUS_SESSION. */
+
+ if (first) {
+ type = PyInt_AsLong(first);
+
+ if (type != DBUS_BUS_SESSION && type != DBUS_BUS_SYSTEM
+ && type != DBUS_BUS_STARTER) {
+ PyErr_Format(PyExc_ValueError, "Unknown bus type %ld", type);
+ return NULL;
+ }
+ }
+ else {
+ type = DBUS_BUS_SESSION;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ conn = dbus_bus_get_private(type, &error);
+ Py_END_ALLOW_THREADS
+
+ if (!conn) {
+ DBusPyException_ConsumeError(&error);
+ return NULL;
+ }
+
+ libdbusconn = DBusPyLibDBusConnection_New (conn);
+ dbus_connection_unref (conn);
+
+ if (!libdbusconn)
+ return NULL;
+
+ new_args = PyTuple_Pack(2, libdbusconn, mainloop ? mainloop : Py_None);
+ Py_DECREF(libdbusconn);
+
+ if (!new_args) {
+ return NULL;
+ }
+
+ new_kwargs = PyDict_New();
+
+ if (!new_kwargs) {
+ Py_DECREF(new_args);
+ return NULL;
+ }
+
+ self = (Connection *)(DBusPyConnection_Type.tp_new)(cls, new_args,
+ new_kwargs);
+ Py_DECREF(new_args);
+ Py_DECREF(new_kwargs);
+
+ return (PyObject *)self; /* whether NULL or not */
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "A string address or an integer "
+ "bus type is required");
+ return NULL;
+ }
+}
+
+PyObject *
+DBusPyConnection_GetUniqueName(Connection *self, PyObject *args UNUSED)
+{
+ const char *name;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ name = dbus_bus_get_unique_name(self->conn);
+ Py_END_ALLOW_THREADS
+ if (!name) {
+ return DBusPyException_SetString("This connection has no unique name "
+ "yet");
+ }
+ return PyString_FromString(name);
+}
+
+PyObject *
+DBusPyConnection_SetUniqueName(Connection *self, PyObject *args)
+{
+ const char *old_name, *new_name;
+
+ if (!PyArg_ParseTuple(args, "s:set_unique_name", &new_name)) {
+ return NULL;
+ }
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+
+ /* libdbus will assert if we try to set a unique name when there's
+ * already one, so we need to make sure that can't happen.
+ * (Thanks, libdbus.)
+ *
+ * The things that can set the unique name are:
+ * - this function - but we don't release the GIL, so only one instance of
+ * this function can run
+ * - dbus_bus_get - but this is only called in a __new__ or __new__-like
+ * function, so the new connection isn't available to other code yet
+ * and this function can't be called on it
+ * - dbus_bus_register - same as dbus_bus_get
+ *
+ * Code outside dbus-python shouldn't be setting the unique name, because
+ * we're using a private connection; we have to trust the authors
+ * of mainloop bindings not to do silly things like that.
+ */
+ old_name = dbus_bus_get_unique_name(self->conn);
+ if (old_name != NULL) {
+ PyErr_Format(PyExc_ValueError, "This connection already has a "
+ "unique name: '%s'", old_name);
+ return NULL;
+ }
+ dbus_bus_set_unique_name(self->conn, new_name);
+
+ Py_RETURN_NONE;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/bytes.c b/_dbus_bindings/bytes.c
new file mode 100644
index 0000000..a5648fe
--- /dev/null
+++ b/_dbus_bindings/bytes.c
@@ -0,0 +1,267 @@
+/* D-Bus Byte and ByteArray types.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+#include "types-internal.h"
+
+PyDoc_STRVAR(Byte_tp_doc,
+"An unsigned byte: a subtype of int, with range restricted to [0, 255].\n"
+"\n"
+"A Byte b may be converted to a str of length 1 via str(b) == chr(b).\n"
+"\n"
+"Most of the time you don't want to use this class - it mainly exists\n"
+"for symmetry with the other D-Bus types. See `dbus.ByteArray` for a\n"
+"better way to handle arrays of Byte.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Byte(integer or str of length 1[, variant_level])\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a byte, this is represented in Python by a\n"
+" Byte with variant_level==2.\n"
+);
+
+static PyObject *
+Byte_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *obj;
+ PyObject *tuple;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError, "Byte constructor takes no more "
+ "than one positional argument");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ /* obj is only a borrowed ref for the moment */
+ obj = PyTuple_GetItem(args, 0);
+
+ if (PyString_Check(obj)) {
+ /* string of length 1, we hope */
+ if (PyString_GET_SIZE(obj) != 1) {
+ goto bad_arg;
+ }
+ obj = PyInt_FromLong((unsigned char)(PyString_AS_STRING(obj)[0]));
+ }
+ else if (PyInt_Check(obj)) {
+ long i = PyInt_AS_LONG(obj);
+
+ if (obj->ob_type == cls &&
+ ((DBusPyIntBase *)obj)->variant_level == variantness) {
+ Py_INCREF(obj);
+ return obj;
+ }
+ if (i < 0 || i > 255) goto bad_range;
+ /* else make it a new reference */
+ Py_INCREF(obj);
+ }
+ else {
+ goto bad_arg;
+ }
+
+ tuple = Py_BuildValue("(O)", obj);
+ if (!tuple) return NULL;
+ Py_DECREF(obj);
+ obj = NULL;
+
+ obj = DBusPyIntBase_Type.tp_new(cls, tuple, kwargs);
+ Py_DECREF(tuple);
+ tuple = NULL;
+ return obj;
+
+bad_arg:
+ PyErr_SetString(PyExc_TypeError, "Expected a string of length 1, "
+ "or an int in the range 0-255");
+ return NULL;
+bad_range:
+ PyErr_SetString(PyExc_ValueError, "Integer outside range 0-255");
+ return NULL;
+}
+
+static PyObject *
+Byte_tp_str(PyObject *self)
+{
+ unsigned char str[2] = { (unsigned char)PyInt_AS_LONG(self), 0 };
+ return PyString_FromStringAndSize((char *)str, 1);
+}
+
+PyTypeObject DBusPyByte_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Byte",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ Byte_tp_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Byte_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Byte_new, /* tp_new */
+};
+
+PyDoc_STRVAR(ByteArray_tp_doc,
+"ByteArray is a subtype of str which can be used when you want an\n"
+"efficient immutable representation of a D-Bus byte array (signature 'ay').\n"
+"\n"
+"By default, when byte arrays are converted from D-Bus to Python, they\n"
+"come out as a `dbus.Array` of `dbus.Byte`. This is just for symmetry with\n"
+"the other D-Bus types - in practice, what you usually want is the byte\n"
+"array represented as a string, using this class. To get this, pass the\n"
+"``byte_arrays=True`` keyword argument to any of these methods:\n"
+"\n"
+"* any D-Bus method proxy, or ``connect_to_signal``, on the objects returned\n"
+" by `Bus.get_object`\n"
+"* any D-Bus method on a `dbus.Interface`\n"
+"* `dbus.Interface.connect_to_signal`\n"
+"* `Bus.add_signal_receiver`\n"
+"\n"
+"Import via::\n"
+"\n"
+" from dbus import ByteArray\n"
+"\n"
+"Constructor::\n"
+"\n"
+" ByteArray(str)\n"
+);
+
+PyTypeObject DBusPyByteArray_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.ByteArray",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ByteArray_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyStrBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_byte_types(void)
+{
+ DBusPyByte_Type.tp_base = &DBusPyIntBase_Type;
+ if (PyType_Ready(&DBusPyByte_Type) < 0) return 0;
+ DBusPyByte_Type.tp_print = NULL;
+
+ DBusPyByteArray_Type.tp_base = &DBusPyStrBase_Type;
+ if (PyType_Ready(&DBusPyByteArray_Type) < 0) return 0;
+ DBusPyByteArray_Type.tp_print = NULL;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_byte_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyByte_Type);
+ if (PyModule_AddObject(this_module, "Byte",
+ (PyObject *)&DBusPyByte_Type) < 0) return 0;
+ Py_INCREF(&DBusPyByteArray_Type);
+ if (PyModule_AddObject(this_module, "ByteArray",
+ (PyObject *)&DBusPyByteArray_Type) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/conn-internal.h b/_dbus_bindings/conn-internal.h
new file mode 100644
index 0000000..f4c7a80
--- /dev/null
+++ b/_dbus_bindings/conn-internal.h
@@ -0,0 +1,67 @@
+/* _dbus_bindings internal API. For use within _dbus_bindings only.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DBUS_BINDINGS_CONN_H
+#define DBUS_BINDINGS_CONN_H
+
+#include "dbus_bindings-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ DBusConnection *conn;
+ /* A list of filter callbacks. */
+ PyObject *filters;
+ /* A dict mapping object paths to one of:
+ * - tuples (unregister_callback or None, message_callback)
+ * - None (meaning unregistration from libdbus is in progress and nobody
+ * should touch this entry til we're finished)
+ */
+ PyObject *object_paths;
+
+ /* Weak-references list to make Connections weakly referenceable */
+ PyObject *weaklist;
+
+ dbus_bool_t has_mainloop;
+} Connection;
+
+typedef struct {
+ PyObject_HEAD
+ DBusConnection *conn;
+} DBusPyLibDBusConnection;
+
+extern struct PyMethodDef DBusPyConnection_tp_methods[];
+extern DBusHandlerResult DBusPyConnection_HandleMessage(Connection *,
+ PyObject *,
+ PyObject *);
+extern PyObject *DBusPyConnection_ExistingFromDBusConnection(DBusConnection *);
+extern PyObject *DBusPyConnection_GetObjectPathHandlers(PyObject *self,
+ PyObject *path);
+
+extern PyObject *DBusPyConnection_NewForBus(PyTypeObject *cls, PyObject *args,
+ PyObject *kwargs);
+extern PyObject *DBusPyConnection_SetUniqueName(Connection *, PyObject *);
+extern PyObject *DBusPyConnection_GetUniqueName(Connection *, PyObject *);
+
+#endif
diff --git a/_dbus_bindings/conn-methods.c b/_dbus_bindings/conn-methods.c
new file mode 100644
index 0000000..81c4514
--- /dev/null
+++ b/_dbus_bindings/conn-methods.c
@@ -0,0 +1,1037 @@
+/* Implementation of normal Python-accessible methods on the _dbus_bindings
+ * Connection type; separated out to keep the file size manageable.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include "conn-internal.h"
+
+static void
+_object_path_unregister(DBusConnection *conn, void *user_data)
+{
+ PyGILState_STATE gil = PyGILState_Ensure();
+ PyObject *tuple = NULL;
+ Connection *conn_obj = NULL;
+ PyObject *callable;
+
+ conn_obj = (Connection *)DBusPyConnection_ExistingFromDBusConnection(conn);
+ if (!conn_obj) goto out;
+ TRACE(conn_obj);
+
+ DBG("Connection at %p unregistering object path %s",
+ conn_obj, PyString_AS_STRING((PyObject *)user_data));
+ tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data);
+ if (!tuple) goto out;
+ if (tuple == Py_None) goto out;
+
+ DBG("%s", "... yes we have handlers for that object path");
+
+ /* 0'th item is the unregisterer (if that's a word) */
+ callable = PyTuple_GetItem(tuple, 0);
+ if (callable && callable != Py_None) {
+ DBG("%s", "... and we even have an unregisterer");
+ /* any return from the unregisterer is ignored */
+ Py_XDECREF(PyObject_CallFunctionObjArgs(callable, conn_obj, NULL));
+ }
+out:
+ Py_XDECREF(conn_obj);
+ Py_XDECREF(tuple);
+ /* the user_data (a Python str) is no longer ref'd by the DBusConnection */
+ Py_XDECREF((PyObject *)user_data);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+ PyGILState_Release(gil);
+}
+
+static DBusHandlerResult
+_object_path_message(DBusConnection *conn, DBusMessage *message,
+ void *user_data)
+{
+ DBusHandlerResult ret;
+ PyGILState_STATE gil = PyGILState_Ensure();
+ Connection *conn_obj = NULL;
+ PyObject *tuple = NULL;
+ PyObject *msg_obj;
+ PyObject *callable; /* borrowed */
+
+ dbus_message_ref(message);
+ msg_obj = DBusPyMessage_ConsumeDBusMessage(message);
+ if (!msg_obj) {
+ ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto out;
+ }
+
+ conn_obj = (Connection *)DBusPyConnection_ExistingFromDBusConnection(conn);
+ if (!conn_obj) {
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto out;
+ }
+ TRACE(conn_obj);
+
+ DBG("Connection at %p messaging object path %s",
+ conn_obj, PyString_AS_STRING((PyObject *)user_data));
+ DBG_DUMP_MESSAGE(message);
+ tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data);
+ if (!tuple || tuple == Py_None) {
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto out;
+ }
+
+ DBG("%s", "... yes we have handlers for that object path");
+
+ /* 1st item (0-based) is the message callback */
+ callable = PyTuple_GetItem(tuple, 1);
+ if (!callable) {
+ DBG("%s", "... error getting message handler from tuple");
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else if (callable == Py_None) {
+ /* there was actually no handler after all */
+ DBG("%s", "... but those handlers don't do messages");
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else {
+ DBG("%s", "... and we have a message handler for that object path");
+ ret = DBusPyConnection_HandleMessage(conn_obj, msg_obj, callable);
+ }
+
+out:
+ Py_XDECREF(msg_obj);
+ Py_XDECREF(conn_obj);
+ Py_XDECREF(tuple);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+ PyGILState_Release(gil);
+ return ret;
+}
+
+static const DBusObjectPathVTable _object_path_vtable = {
+ _object_path_unregister,
+ _object_path_message,
+};
+
+static DBusHandlerResult
+_filter_message(DBusConnection *conn, DBusMessage *message, void *user_data)
+{
+ DBusHandlerResult ret;
+ PyGILState_STATE gil = PyGILState_Ensure();
+ Connection *conn_obj = NULL;
+ PyObject *callable = NULL;
+ PyObject *msg_obj;
+#ifndef DBUS_PYTHON_DISABLE_CHECKS
+ Py_ssize_t i, size;
+#endif
+
+ dbus_message_ref(message);
+ msg_obj = DBusPyMessage_ConsumeDBusMessage(message);
+ if (!msg_obj) {
+ DBG("%s", "OOM while trying to construct Message");
+ ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto out;
+ }
+
+ conn_obj = (Connection *)DBusPyConnection_ExistingFromDBusConnection(conn);
+ if (!conn_obj) {
+ DBG("%s", "failed to traverse DBusConnection -> Connection weakref");
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto out;
+ }
+ TRACE(conn_obj);
+
+ /* The user_data is a pointer to a Python object. To avoid
+ * cross-library reference cycles, the DBusConnection isn't allowed
+ * to reference it. However, as long as the Connection is still
+ * alive, its ->filters list owns a reference to the same Python
+ * object, so the object should also still be alive.
+ *
+ * To ensure that this works, be careful whenever manipulating the
+ * filters list! (always put things in the list *before* giving
+ * them to libdbus, etc.)
+ */
+#ifdef DBUS_PYTHON_DISABLE_CHECKS
+ callable = (PyObject *)user_data;
+#else
+ size = PyList_GET_SIZE(conn_obj->filters);
+ for (i = 0; i < size; i++) {
+ callable = PyList_GET_ITEM(conn_obj->filters, i);
+ if (callable == user_data) {
+ Py_INCREF(callable);
+ break;
+ }
+ else {
+ callable = NULL;
+ }
+ }
+
+ if (!callable) {
+ DBG("... filter %p has vanished from ->filters, so not calling it",
+ user_data);
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto out;
+ }
+#endif
+
+ ret = DBusPyConnection_HandleMessage(conn_obj, msg_obj, callable);
+out:
+ Py_XDECREF(msg_obj);
+ Py_XDECREF(conn_obj);
+ Py_XDECREF(callable);
+ PyGILState_Release(gil);
+ return ret;
+}
+
+PyDoc_STRVAR(Connection__require_main_loop__doc__,
+"_require_main_loop()\n\n"
+"Raise an exception if this Connection is not bound to any main loop -\n"
+"in this state, asynchronous calls, receiving signals and exporting objects\n"
+"will not work.\n"
+"\n"
+"`dbus.mainloop.NULL_MAIN_LOOP` is treated like a valid main loop - if you're\n"
+"using that, you presumably know what you're doing.\n");
+static PyObject *
+Connection__require_main_loop (Connection *self, PyObject *args UNUSED)
+{
+ if (!self->has_mainloop) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "To make asynchronous calls, receive signals or "
+ "export objects, D-Bus connections must be attached "
+ "to a main loop by passing mainloop=... to the "
+ "constructor or calling "
+ "dbus.set_default_main_loop(...)");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Connection_close__doc__,
+"close()\n\n"
+"Close the connection.");
+static PyObject *
+Connection_close (Connection *self, PyObject *args UNUSED)
+{
+ TRACE(self);
+ /* Because the user explicitly asked to close the connection, we'll even
+ let them close shared connections. */
+ if (self->conn) {
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_close(self->conn);
+ Py_END_ALLOW_THREADS
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Connection_get_is_connected__doc__,
+"get_is_connected() -> bool\n\n"
+"Return true if this Connection is connected.\n");
+static PyObject *
+Connection_get_is_connected (Connection *self, PyObject *args UNUSED)
+{
+ dbus_bool_t ret;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_connection_get_is_connected(self->conn);
+ Py_END_ALLOW_THREADS
+ return PyBool_FromLong(ret);
+}
+
+PyDoc_STRVAR(Connection_get_is_authenticated__doc__,
+"get_is_authenticated() -> bool\n\n"
+"Return true if this Connection was ever authenticated.\n");
+static PyObject *
+Connection_get_is_authenticated (Connection *self, PyObject *args UNUSED)
+{
+ dbus_bool_t ret;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_connection_get_is_authenticated(self->conn);
+ Py_END_ALLOW_THREADS
+ return PyBool_FromLong(ret);
+}
+
+PyDoc_STRVAR(Connection_set_exit_on_disconnect__doc__,
+"set_exit_on_disconnect(bool)\n\n"
+"Set whether the C function ``_exit`` will be called when this Connection\n"
+"becomes disconnected. This will cause the program to exit without calling\n"
+"any cleanup code or exit handlers.\n"
+"\n"
+"The default is for this feature to be disabled for Connections and enabled\n"
+"for Buses.\n");
+static PyObject *
+Connection_set_exit_on_disconnect (Connection *self, PyObject *args)
+{
+ int exit_on_disconnect;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTuple(args, "i:set_exit_on_disconnect",
+ &exit_on_disconnect)) {
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_set_exit_on_disconnect(self->conn,
+ exit_on_disconnect ? 1 : 0);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Connection_send_message__doc__,
+"send_message(msg) -> long\n\n"
+"Queue the given message for sending, and return the message serial number.\n"
+"\n"
+":Parameters:\n"
+" `msg` : dbus.lowlevel.Message\n"
+" The message to be sent.\n"
+);
+static PyObject *
+Connection_send_message(Connection *self, PyObject *args)
+{
+ dbus_bool_t ok;
+ PyObject *obj;
+ DBusMessage *msg;
+ dbus_uint32_t serial;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTuple(args, "O", &obj)) return NULL;
+
+ msg = DBusPyMessage_BorrowDBusMessage(obj);
+ if (!msg) return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_send(self->conn, msg, &serial);
+ Py_END_ALLOW_THREADS
+
+ if (!ok) {
+ return PyErr_NoMemory();
+ }
+
+ return PyLong_FromUnsignedLong(serial);
+}
+
+/* The timeout is in seconds here, since that's conventional in Python. */
+PyDoc_STRVAR(Connection_send_message_with_reply__doc__,
+"send_message_with_reply(msg, reply_handler, timeout_s=-1, "
+"require_main_loop=False) -> dbus.lowlevel.PendingCall\n\n"
+"Queue the message for sending; expect a reply via the returned PendingCall,\n"
+"which can also be used to cancel the pending call.\n"
+"\n"
+":Parameters:\n"
+" `msg` : dbus.lowlevel.Message\n"
+" The message to be sent\n"
+" `reply_handler` : callable\n"
+" Asynchronous reply handler: will be called with one positional\n"
+" parameter, a Message instance representing the reply.\n"
+" `timeout_s` : float\n"
+" If the reply takes more than this many seconds, a timeout error\n"
+" will be created locally and raised instead. If this timeout is\n"
+" negative (default), a sane default (supplied by libdbus) is used.\n"
+" `require_main_loop` : bool\n"
+" If True, raise RuntimeError if this Connection does not have a main\n"
+" loop configured. If False (default) and there is no main loop, you are\n"
+" responsible for calling block() on the PendingCall.\n"
+"\n"
+);
+static PyObject *
+Connection_send_message_with_reply(Connection *self, PyObject *args, PyObject *kw)
+{
+ dbus_bool_t ok;
+ double timeout_s = -1.0;
+ int timeout_ms;
+ PyObject *obj, *callable;
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+ int require_main_loop = 0;
+ static char *argnames[] = {"msg", "reply_handler", "timeout_s",
+ "require_main_loop", NULL};
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+ "OO|di:send_message_with_reply",
+ argnames,
+ &obj, &callable, &timeout_s,
+ &require_main_loop)) {
+ return NULL;
+ }
+ if (require_main_loop && !Connection__require_main_loop(self, NULL)) {
+ return NULL;
+ }
+
+ msg = DBusPyMessage_BorrowDBusMessage(obj);
+ if (!msg) return NULL;
+
+ if (timeout_s < 0) {
+ timeout_ms = -1;
+ }
+ else {
+ if (timeout_s > ((double)INT_MAX) / 1000.0) {
+ PyErr_SetString(PyExc_ValueError, "Timeout too long");
+ return NULL;
+ }
+ timeout_ms = (int)(timeout_s * 1000.0);
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_send_with_reply(self->conn, msg, &pending,
+ timeout_ms);
+ Py_END_ALLOW_THREADS
+
+ if (!ok) {
+ return PyErr_NoMemory();
+ }
+
+ if (!pending) {
+ /* connection is disconnected (doesn't return FALSE!) */
+ return DBusPyException_SetString ("Connection is disconnected - "
+ "unable to make method call");
+ }
+
+ return DBusPyPendingCall_ConsumeDBusPendingCall(pending, callable);
+}
+
+/* Again, the timeout is in seconds, since that's conventional in Python. */
+PyDoc_STRVAR(Connection_send_message_with_reply_and_block__doc__,
+"send_message_with_reply_and_block(msg, timeout_s=-1)"
+" -> dbus.lowlevel.Message\n\n"
+"Send the message and block while waiting for a reply.\n"
+"\n"
+"This does not re-enter the main loop, so it can lead to a deadlock, if\n"
+"the called method tries to make a synchronous call to a method in this\n"
+"application. As such, it's probably a bad idea.\n"
+"\n"
+":Parameters:\n"
+" `msg` : dbus.lowlevel.Message\n"
+" The message to be sent\n"
+" `timeout_s` : float\n"
+" If the reply takes more than this many seconds, a timeout error\n"
+" will be created locally and raised instead. If this timeout is\n"
+" negative (default), a sane default (supplied by libdbus) is used.\n"
+":Returns:\n"
+" A `dbus.lowlevel.Message` instance (probably a `dbus.lowlevel.MethodReturnMessage`) on success\n"
+":Raises dbus.DBusException:\n"
+" On error (including if the reply arrives but is an\n"
+" error message)\n"
+"\n"
+);
+static PyObject *
+Connection_send_message_with_reply_and_block(Connection *self, PyObject *args)
+{
+ double timeout_s = -1.0;
+ int timeout_ms;
+ PyObject *obj;
+ DBusMessage *msg, *reply;
+ DBusError error;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTuple(args, "O|d:send_message_with_reply_and_block", &obj,
+ &timeout_s)) {
+ return NULL;
+ }
+
+ msg = DBusPyMessage_BorrowDBusMessage(obj);
+ if (!msg) return NULL;
+
+ if (timeout_s < 0) {
+ timeout_ms = -1;
+ }
+ else {
+ if (timeout_s > ((double)INT_MAX) / 1000.0) {
+ PyErr_SetString(PyExc_ValueError, "Timeout too long");
+ return NULL;
+ }
+ timeout_ms = (int)(timeout_s * 1000.0);
+ }
+
+ dbus_error_init(&error);
+ Py_BEGIN_ALLOW_THREADS
+ reply = dbus_connection_send_with_reply_and_block(self->conn, msg,
+ timeout_ms, &error);
+ Py_END_ALLOW_THREADS
+
+ /* FIXME: if we instead used send_with_reply and blocked on the resulting
+ * PendingCall, then we could get all args from the error, not just
+ * the first */
+ if (!reply) {
+ return DBusPyException_ConsumeError(&error);
+ }
+ return DBusPyMessage_ConsumeDBusMessage(reply);
+}
+
+PyDoc_STRVAR(Connection_flush__doc__,
+"flush()\n\n"
+"Block until the outgoing message queue is empty.\n");
+static PyObject *
+Connection_flush (Connection *self, PyObject *args UNUSED)
+{
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_flush (self->conn);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+/* Unsupported:
+ * dbus_connection_preallocate_send
+ * dbus_connection_free_preallocated_send
+ * dbus_connection_send_preallocated
+ * dbus_connection_borrow_message
+ * dbus_connection_return_message
+ * dbus_connection_steal_borrowed_message
+ * dbus_connection_pop_message
+ */
+
+/* Non-main-loop handling not yet implemented: */
+ /* dbus_connection_read_write_dispatch */
+ /* dbus_connection_read_write */
+
+/* Main loop handling not yet implemented: */
+ /* dbus_connection_get_dispatch_status */
+ /* dbus_connection_dispatch */
+ /* dbus_connection_set_watch_functions */
+ /* dbus_connection_set_timeout_functions */
+ /* dbus_connection_set_wakeup_main_function */
+ /* dbus_connection_set_dispatch_status_function */
+
+/* Normally in Python this would be called fileno(), but I don't want to
+ * encourage people to select() on it */
+PyDoc_STRVAR(Connection_get_unix_fd__doc__,
+"get_unix_fd() -> int or None\n\n"
+"Get the connection's UNIX file descriptor, if any.\n\n"
+"This can be used for SELinux access control checks with ``getpeercon()``\n"
+"for example. **Do not** read or write to the file descriptor, or try to\n"
+"``select()`` on it.\n");
+static PyObject *
+Connection_get_unix_fd (Connection *self, PyObject *unused UNUSED)
+{
+ int fd;
+ dbus_bool_t ok;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_get_unix_fd (self->conn, &fd);
+ Py_END_ALLOW_THREADS
+ if (!ok) Py_RETURN_NONE;
+ return PyInt_FromLong(fd);
+}
+
+PyDoc_STRVAR(Connection_get_peer_unix_user__doc__,
+"get_peer_unix_user() -> long or None\n\n"
+"Get the UNIX user ID at the other end of the connection, if it has been\n"
+"authenticated. Return None if this is a non-UNIX platform or the\n"
+"connection has not been authenticated.\n");
+static PyObject *
+Connection_get_peer_unix_user (Connection *self, PyObject *unused UNUSED)
+{
+ unsigned long uid;
+ dbus_bool_t ok;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_get_unix_user (self->conn, &uid);
+ Py_END_ALLOW_THREADS
+ if (!ok) Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (uid);
+}
+
+PyDoc_STRVAR(Connection_get_peer_unix_process_id__doc__,
+"get_peer_unix_process_id() -> long or None\n\n"
+"Get the UNIX process ID at the other end of the connection, if it has been\n"
+"authenticated. Return None if this is a non-UNIX platform or the\n"
+"connection has not been authenticated.\n");
+static PyObject *
+Connection_get_peer_unix_process_id (Connection *self, PyObject *unused UNUSED)
+{
+ unsigned long pid;
+ dbus_bool_t ok;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_get_unix_process_id (self->conn, &pid);
+ Py_END_ALLOW_THREADS
+ if (!ok) Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (pid);
+}
+
+/* TODO: wrap dbus_connection_set_unix_user_function Pythonically */
+
+PyDoc_STRVAR(Connection_add_message_filter__doc__,
+"add_message_filter(callable)\n\n"
+"Add the given message filter to the internal list.\n\n"
+"Filters are handlers that are run on all incoming messages, prior to the\n"
+"objects registered to handle object paths.\n"
+"\n"
+"Filters are run in the order that they were added. The same handler can\n"
+"be added as a filter more than once, in which case it will be run more\n"
+"than once. Filters added during a filter callback won't be run on the\n"
+"message being processed.\n"
+);
+static PyObject *
+Connection_add_message_filter(Connection *self, PyObject *callable)
+{
+ dbus_bool_t ok;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ /* The callable must be referenced by ->filters *before* it is
+ * given to libdbus, which does not own a reference to it.
+ */
+ if (PyList_Append(self->filters, callable) < 0) {
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_add_filter(self->conn, _filter_message, callable,
+ NULL);
+ Py_END_ALLOW_THREADS
+
+ if (!ok) {
+ Py_XDECREF(PyObject_CallMethod(self->filters, "remove", "(O)",
+ callable));
+ PyErr_NoMemory();
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Connection_remove_message_filter__doc__,
+"remove_message_filter(callable)\n\n"
+"Remove the given message filter (see `add_message_filter` for details).\n"
+"\n"
+":Raises LookupError:\n"
+" The given callable is not among the registered filters\n");
+static PyObject *
+Connection_remove_message_filter(Connection *self, PyObject *callable)
+{
+ PyObject *obj;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ /* It's safe to do this before removing it from libdbus, because
+ * the presence of callable in our arguments means we have a ref
+ * to it. */
+ obj = PyObject_CallMethod(self->filters, "remove", "(O)", callable);
+ if (!obj) return NULL;
+ Py_DECREF(obj);
+
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_remove_filter(self->conn, _filter_message, callable);
+ Py_END_ALLOW_THREADS
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Connection__register_object_path__doc__,
+"register_object_path(path, on_message, on_unregister=None, fallback=False)\n"
+"\n"
+"Register a callback to be called when messages arrive at the given\n"
+"object-path. Used to export objects' methods on the bus in a low-level\n"
+"way. For the high-level interface to this functionality (usually\n"
+"recommended) see the `dbus.service.Object` base class.\n"
+"\n"
+":Parameters:\n"
+" `path` : str\n"
+" Object path to be acted on\n"
+" `on_message` : callable\n"
+" Called when a message arrives at the given object-path, with\n"
+" two positional parameters: the first is this Connection,\n"
+" the second is the incoming `dbus.lowlevel.Message`.\n"
+" `on_unregister` : callable or None\n"
+" If not None, called when the callback is unregistered.\n"
+" `fallback` : bool\n"
+" If True (the default is False), when a message arrives for a\n"
+" 'subdirectory' of the given path and there is no more specific\n"
+" handler, use this handler. Normally this handler is only run if\n"
+" the paths match exactly.\n"
+);
+static PyObject *
+Connection__register_object_path(Connection *self, PyObject *args,
+ PyObject *kwargs)
+{
+ dbus_bool_t ok;
+ int fallback = 0;
+ PyObject *callbacks, *path, *tuple, *on_message, *on_unregister = Py_None;
+ static char *argnames[] = {"path", "on_message", "on_unregister",
+ "fallback", NULL};
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!Connection__require_main_loop(self, NULL)) {
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "OO|Oi:_register_object_path",
+ argnames,
+ &path,
+ &on_message, &on_unregister,
+ &fallback)) return NULL;
+
+ /* Take a reference to path, which we give away to libdbus in a moment.
+
+ Also, path needs to be a string (not a subclass which could do something
+ mad) to preserve the desirable property that the DBusConnection can
+ never strongly reference the Connection, even indirectly.
+ */
+ if (PyString_CheckExact(path)) {
+ Py_INCREF(path);
+ }
+ else if (PyUnicode_Check(path)) {
+ path = PyUnicode_AsUTF8String(path);
+ if (!path) return NULL;
+ }
+ else if (PyString_Check(path)) {
+ path = PyString_FromString(PyString_AS_STRING(path));
+ if (!path) return NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object");
+ return NULL;
+ }
+
+ if (!dbus_py_validate_object_path(PyString_AS_STRING(path))) {
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ tuple = Py_BuildValue("(OO)", on_unregister, on_message);
+ if (!tuple) {
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ /* Guard against registering a handler that already exists. */
+ callbacks = PyDict_GetItem(self->object_paths, path);
+ if (callbacks && callbacks != Py_None) {
+ PyErr_Format(PyExc_KeyError, "Can't register the object-path "
+ "handler for '%s': there is already a handler",
+ PyString_AS_STRING(path));
+ Py_DECREF(tuple);
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ /* Pre-allocate a slot in the dictionary, so we know we'll be able
+ * to replace it with the callbacks without OOM.
+ * This ensures we can keep libdbus' opinion of whether those
+ * paths are handled in sync with our own. */
+ if (PyDict_SetItem(self->object_paths, path, Py_None) < 0) {
+ Py_DECREF(tuple);
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ if (fallback) {
+ ok = dbus_connection_register_fallback(self->conn,
+ PyString_AS_STRING(path),
+ &_object_path_vtable,
+ path);
+ }
+ else {
+ ok = dbus_connection_register_object_path(self->conn,
+ PyString_AS_STRING(path),
+ &_object_path_vtable,
+ path);
+ }
+ Py_END_ALLOW_THREADS
+
+ if (ok) {
+ if (PyDict_SetItem(self->object_paths, path, tuple) < 0) {
+ /* That shouldn't have happened, we already allocated enough
+ memory for it. Oh well, try to undo the registration to keep
+ things in sync. If this fails too, we've leaked a bit of
+ memory in libdbus, but tbh we should never get here anyway. */
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_unregister_object_path(self->conn,
+ PyString_AS_STRING(path));
+ Py_END_ALLOW_THREADS
+ return NULL;
+ }
+ /* don't DECREF path: libdbus owns a ref now */
+ Py_DECREF(tuple);
+ Py_RETURN_NONE;
+ }
+ else {
+ /* Oops, OOM. Tidy up, if we can, ignoring any error. */
+ PyDict_DelItem(self->object_paths, path);
+ PyErr_Clear();
+ Py_DECREF(tuple);
+ Py_DECREF(path);
+ PyErr_NoMemory();
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(Connection__unregister_object_path__doc__,
+"unregister_object_path(path)\n\n"
+"Remove a previously registered handler for the given object path.\n"
+"\n"
+":Parameters:\n"
+" `path` : str\n"
+" The object path whose handler is to be removed\n"
+":Raises KeyError: if there is no handler registered for exactly that\n"
+" object path.\n"
+);
+static PyObject *
+Connection__unregister_object_path(Connection *self, PyObject *args,
+ PyObject *kwargs)
+{
+ dbus_bool_t ok;
+ PyObject *path;
+ PyObject *callbacks;
+ static char *argnames[] = {"path", NULL};
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:_unregister_object_path",
+ argnames, &path)) return NULL;
+
+ /* Take a ref to the path. Same comments as for _register_object_path. */
+ if (PyString_CheckExact(path)) {
+ Py_INCREF(path);
+ }
+ else if (PyUnicode_Check(path)) {
+ path = PyUnicode_AsUTF8String(path);
+ if (!path) return NULL;
+ }
+ else if (PyString_Check(path)) {
+ path = PyString_FromString(PyString_AS_STRING(path));
+ if (!path) return NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object");
+ return NULL;
+ }
+
+ /* Guard against unregistering a handler that doesn't, in fact, exist,
+ or whose unregistration is already in progress. */
+ callbacks = PyDict_GetItem(self->object_paths, path);
+ if (!callbacks || callbacks == Py_None) {
+ PyErr_Format(PyExc_KeyError, "Can't unregister the object-path "
+ "handler for '%s': there is no such handler",
+ PyString_AS_STRING(path));
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ /* Hang on to a reference to the callbacks for the moment. */
+ Py_INCREF(callbacks);
+
+ /* Get rid of the object-path while we still have the GIL, to
+ guard against unregistering twice from different threads (which
+ causes undefined behaviour in libdbus).
+
+ Because deletion would make it possible for the re-insertion below
+ to fail, we instead set the handler to None as a placeholder.
+ */
+ if (PyDict_SetItem(self->object_paths, path, Py_None) < 0) {
+ /* If that failed, there's no need to be paranoid as below - the
+ callbacks are still set, so we failed, but at least everything
+ is in sync. */
+ Py_DECREF(callbacks);
+ Py_DECREF(path);
+ return NULL;
+ }
+
+ /* BEGIN PARANOIA
+ This is something of a critical section - the dict of object-paths
+ and libdbus' internal structures are out of sync for a bit. We have
+ to be able to cope with that.
+
+ It's really annoying that dbus_connection_unregister_object_path
+ can fail, *and* has undefined behaviour if the object path has
+ already been unregistered. Either/or would be fine.
+ */
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_unregister_object_path(self->conn,
+ PyString_AS_STRING(path));
+ Py_END_ALLOW_THREADS
+
+ if (ok) {
+ Py_DECREF(callbacks);
+ PyDict_DelItem(self->object_paths, path);
+ /* END PARANOIA on successful code path */
+ /* The above can't fail unless by some strange trickery the key is no
+ longer present. Ignore any errors. */
+ Py_DECREF(path);
+ PyErr_Clear();
+ Py_RETURN_NONE;
+ }
+ else {
+ /* Oops, OOM. Put the callbacks back in the dict so
+ * we'll have another go if/when the user frees some memory
+ * and tries calling this method again. */
+ PyDict_SetItem(self->object_paths, path, callbacks);
+ /* END PARANOIA on failing code path */
+ /* If the SetItem failed, there's nothing we can do about it - but
+ since we know it's an existing entry, it shouldn't be able to fail
+ anyway. */
+ Py_DECREF(path);
+ Py_DECREF(callbacks);
+ return PyErr_NoMemory();
+ }
+}
+
+PyDoc_STRVAR(Connection_list_exported_child_objects__doc__,
+"list_exported_child_objects(path: str) -> list of str\n\n"
+"Return a list of the names of objects exported on this Connection as\n"
+"direct children of the given object path.\n"
+"\n"
+"Each name returned may be converted to a valid object path using\n"
+"``dbus.ObjectPath('%s%s%s' % (path, (path != '/' and '/' or ''), name))``.\n"
+"For the purposes of this function, every parent or ancestor of an exported\n"
+"object is considered to be an exported object, even if it's only an object\n"
+"synthesized by the library to support introspection.\n");
+static PyObject *
+Connection_list_exported_child_objects (Connection *self, PyObject *args,
+ PyObject *kwargs)
+{
+ const char *path;
+ char **kids, **kid_ptr;
+ dbus_bool_t ok;
+ PyObject *ret;
+ static char *argnames[] = {"path", NULL};
+
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", argnames, &path)) {
+ return NULL;
+ }
+
+ if (!dbus_py_validate_object_path(path)) {
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_list_registered(self->conn, path, &kids);
+ Py_END_ALLOW_THREADS
+
+ if (!ok) {
+ return PyErr_NoMemory();
+ }
+
+ ret = PyList_New(0);
+ if (!ret) {
+ return NULL;
+ }
+ for (kid_ptr = kids; *kid_ptr; kid_ptr++) {
+ PyObject *tmp = PyString_FromString(*kid_ptr);
+
+ if (!tmp) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ if (PyList_Append(ret, tmp) < 0) {
+ Py_DECREF(tmp);
+ Py_DECREF(ret);
+ return NULL;
+ }
+ Py_DECREF(tmp);
+ }
+
+ dbus_free_string_array(kids);
+
+ return ret;
+}
+
+ /* dbus_connection_get_object_path_data - not useful to Python,
+ * the object path data is just a PyString containing the path */
+ /* dbus_connection_list_registered could be useful, though */
+
+/* dbus_connection_set_change_sigpipe - sets global state */
+
+/* Maxima. Does Python code ever need to manipulate these?
+ * OTOH they're easy to wrap */
+ /* dbus_connection_set_max_message_size */
+ /* dbus_connection_get_max_message_size */
+ /* dbus_connection_set_max_received_size */
+ /* dbus_connection_get_max_received_size */
+
+/* dbus_connection_get_outgoing_size - almost certainly unneeded */
+
+PyDoc_STRVAR(new_for_bus__doc__,
+"Connection._new_for_bus([address: str or int]) -> Connection\n"
+"\n"
+"If the address is an int it must be one of the constants BUS_SESSION,\n"
+"BUS_SYSTEM, BUS_STARTER; if a string, it must be a D-Bus address.\n"
+"The default is BUS_SESSION.\n"
+);
+
+PyDoc_STRVAR(get_unique_name__doc__,
+"get_unique_name() -> str\n\n"
+"Return this application's unique name on this bus.\n"
+"\n"
+":Raises DBusException: if the connection has no unique name yet\n"
+" (for Bus objects this can't happen, for peer-to-peer connections\n"
+" this means you haven't called `set_unique_name`)\n");
+
+PyDoc_STRVAR(set_unique_name__doc__,
+"set_unique_name(str)\n\n"
+"Set this application's unique name on this bus. Raise ValueError if it has\n"
+"already been set.\n");
+
+struct PyMethodDef DBusPyConnection_tp_methods[] = {
+#define ENTRY(name, flags) {#name, (PyCFunction)Connection_##name, flags, Connection_##name##__doc__}
+ ENTRY(_require_main_loop, METH_NOARGS),
+ ENTRY(close, METH_NOARGS),
+ ENTRY(flush, METH_NOARGS),
+ ENTRY(get_is_connected, METH_NOARGS),
+ ENTRY(get_is_authenticated, METH_NOARGS),
+ ENTRY(set_exit_on_disconnect, METH_VARARGS),
+ ENTRY(get_unix_fd, METH_NOARGS),
+ ENTRY(get_peer_unix_user, METH_NOARGS),
+ ENTRY(get_peer_unix_process_id, METH_NOARGS),
+ ENTRY(add_message_filter, METH_O),
+ ENTRY(_register_object_path, METH_VARARGS|METH_KEYWORDS),
+ ENTRY(remove_message_filter, METH_O),
+ ENTRY(send_message, METH_VARARGS),
+ ENTRY(send_message_with_reply, METH_VARARGS|METH_KEYWORDS),
+ ENTRY(send_message_with_reply_and_block, METH_VARARGS),
+ ENTRY(_unregister_object_path, METH_VARARGS|METH_KEYWORDS),
+ ENTRY(list_exported_child_objects, METH_VARARGS|METH_KEYWORDS),
+ {"_new_for_bus", (PyCFunction)DBusPyConnection_NewForBus,
+ METH_CLASS|METH_VARARGS|METH_KEYWORDS,
+ new_for_bus__doc__},
+ {"get_unique_name", (PyCFunction)DBusPyConnection_GetUniqueName,
+ METH_NOARGS,
+ get_unique_name__doc__},
+ {"set_unique_name", (PyCFunction)DBusPyConnection_SetUniqueName,
+ METH_VARARGS,
+ set_unique_name__doc__},
+ {NULL},
+#undef ENTRY
+};
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/conn.c b/_dbus_bindings/conn.c
new file mode 100644
index 0000000..e7c5338
--- /dev/null
+++ b/_dbus_bindings/conn.c
@@ -0,0 +1,471 @@
+/* Implementation of the _dbus_bindings Connection type, a Python wrapper
+ * for DBusConnection. See also conn-methods.c.
+ *
+ * Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include "conn-internal.h"
+
+/* Connection definition ============================================ */
+
+PyDoc_STRVAR(Connection_tp_doc,
+"A D-Bus connection.\n"
+"\n"
+"::\n"
+"\n"
+" Connection(address, mainloop=None) -> Connection\n"
+);
+
+/* D-Bus Connection user data slot, containing an owned reference to either
+ * the Connection, or a weakref to the Connection.
+ */
+static dbus_int32_t _connection_python_slot;
+
+/* C API for main-loop hooks ======================================== */
+
+/* Return a borrowed reference to the DBusConnection which underlies this
+ * Connection. */
+DBusConnection *
+DBusPyConnection_BorrowDBusConnection(PyObject *self)
+{
+ DBusConnection *dbc;
+
+ TRACE(self);
+ if (!DBusPyConnection_Check(self)) {
+ PyErr_SetString(PyExc_TypeError, "A dbus.Connection is required");
+ return NULL;
+ }
+ dbc = ((Connection *)self)->conn;
+ if (!dbc) {
+ PyErr_SetString(PyExc_RuntimeError, "Connection is in an invalid "
+ "state: no DBusConnection");
+ return NULL;
+ }
+ return dbc;
+}
+
+/* Internal C API =================================================== */
+
+/* Pass a message through a handler. */
+DBusHandlerResult
+DBusPyConnection_HandleMessage(Connection *conn,
+ PyObject *msg,
+ PyObject *callable)
+{
+ PyObject *obj;
+
+ TRACE(conn);
+ obj = PyObject_CallFunctionObjArgs(callable, conn, msg,
+ NULL);
+ if (obj == Py_None) {
+ DBG("%p: OK, handler %p returned None", conn, callable);
+ Py_DECREF(obj);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (obj == Py_NotImplemented) {
+ DBG("%p: handler %p returned NotImplemented, continuing",
+ conn, callable);
+ Py_DECREF(obj);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else if (!obj) {
+ if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
+ DBG_EXC("%p: handler %p caused OOM", conn, callable);
+ PyErr_Clear();
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+ DBG_EXC("%p: handler %p raised exception", conn, callable);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else {
+ long i = PyInt_AsLong(obj);
+ DBG("%p: handler %p returned %ld", conn, callable, i);
+ Py_DECREF(obj);
+ if (i == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "Return from D-Bus message "
+ "handler callback should be None, "
+ "NotImplemented or integer");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else if (i == DBUS_HANDLER_RESULT_HANDLED ||
+ i == DBUS_HANDLER_RESULT_NOT_YET_HANDLED ||
+ i == DBUS_HANDLER_RESULT_NEED_MEMORY) {
+ return i;
+ }
+ else {
+ PyErr_Format(PyExc_ValueError, "Integer return from "
+ "D-Bus message handler callback should "
+ "be a DBUS_HANDLER_RESULT_... constant, "
+ "not %d", (int)i);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+}
+
+/* On KeyError or if unregistration is in progress, return None. */
+PyObject *
+DBusPyConnection_GetObjectPathHandlers(PyObject *self, PyObject *path)
+{
+ PyObject *callbacks;
+
+ TRACE(self);
+ callbacks = PyDict_GetItem(((Connection *)self)->object_paths, path);
+ if (!callbacks) {
+ if (PyErr_ExceptionMatches(PyExc_KeyError)) {
+ PyErr_Clear();
+ Py_RETURN_NONE;
+ }
+ }
+ Py_INCREF(callbacks);
+ return callbacks;
+}
+
+/* Return a new reference to a Python Connection or subclass corresponding
+ * to the DBusConnection conn. For use in callbacks.
+ *
+ * Raises AssertionError if the DBusConnection does not have a Connection.
+ */
+PyObject *
+DBusPyConnection_ExistingFromDBusConnection(DBusConnection *conn)
+{
+ PyObject *self, *ref;
+
+ Py_BEGIN_ALLOW_THREADS
+ ref = (PyObject *)dbus_connection_get_data(conn,
+ _connection_python_slot);
+ Py_END_ALLOW_THREADS
+ if (ref) {
+ DBG("(DBusConnection *)%p has weak reference at %p", conn, ref);
+ self = PyWeakref_GetObject(ref); /* still a borrowed ref */
+ if (self && self != Py_None && DBusPyConnection_Check(self)) {
+ DBG("(DBusConnection *)%p has weak reference at %p pointing to %p",
+ conn, ref, self);
+ TRACE(self);
+ Py_INCREF(self);
+ TRACE(self);
+ return self;
+ }
+ }
+
+ PyErr_SetString(PyExc_AssertionError,
+ "D-Bus connection does not have a Connection "
+ "instance associated with it");
+ return NULL;
+}
+
+/* Return a new reference to a Python Connection or subclass (given by cls)
+ * corresponding to the DBusConnection conn, which must have been newly
+ * created. For use by the Connection and Bus constructors.
+ *
+ * Raises AssertionError if the DBusConnection already has a Connection.
+ */
+static PyObject *
+DBusPyConnection_NewConsumingDBusConnection(PyTypeObject *cls,
+ DBusConnection *conn,
+ PyObject *mainloop)
+{
+ Connection *self = NULL;
+ PyObject *ref;
+ dbus_bool_t ok;
+
+ DBG("%s(cls=%p, conn=%p, mainloop=%p)", __func__, cls, conn, mainloop);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(conn);
+
+ Py_BEGIN_ALLOW_THREADS
+ ref = (PyObject *)dbus_connection_get_data(conn,
+ _connection_python_slot);
+ Py_END_ALLOW_THREADS
+ if (ref) {
+ self = (Connection *)PyWeakref_GetObject(ref);
+ ref = NULL;
+ if (self && (PyObject *)self != Py_None) {
+ self = NULL;
+ PyErr_SetString(PyExc_AssertionError,
+ "Newly created D-Bus connection already has a "
+ "Connection instance associated with it");
+ DBG("%s() fail - assertion failed, DBusPyConn has a DBusConn already", __func__);
+ DBG_WHEREAMI;
+ return NULL;
+ }
+ }
+ ref = NULL;
+
+ /* Change mainloop from a borrowed reference to an owned reference */
+ if (!mainloop || mainloop == Py_None) {
+ mainloop = dbus_py_get_default_main_loop();
+ if (!mainloop)
+ goto err;
+ }
+ else {
+ Py_INCREF(mainloop);
+ }
+
+ DBG("Constructing Connection from DBusConnection at %p", conn);
+
+ self = (Connection *)(cls->tp_alloc(cls, 0));
+ if (!self) goto err;
+ TRACE(self);
+
+ DBG_WHEREAMI;
+
+ self->has_mainloop = (mainloop != Py_None);
+ self->conn = NULL;
+ self->filters = PyList_New(0);
+ if (!self->filters) goto err;
+ self->object_paths = PyDict_New();
+ if (!self->object_paths) goto err;
+
+ ref = PyWeakref_NewRef((PyObject *)self, NULL);
+ if (!ref) goto err;
+ DBG("Created weak ref %p to (Connection *)%p for (DBusConnection *)%p",
+ ref, self, conn);
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_connection_set_data(conn, _connection_python_slot,
+ (void *)ref,
+ (DBusFreeFunction)dbus_py_take_gil_and_xdecref);
+ Py_END_ALLOW_THREADS
+
+ if (ok) {
+ DBG("Attached weak ref %p ((Connection *)%p) to (DBusConnection *)%p",
+ ref, self, conn);
+ ref = NULL; /* don't DECREF it - the DBusConnection owns it now */
+ }
+ else {
+ DBG("Failed to attached weak ref %p ((Connection *)%p) to "
+ "(DBusConnection *)%p - will dispose of it", ref, self, conn);
+ PyErr_NoMemory();
+ goto err;
+ }
+
+ DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(conn, err);
+ self->conn = conn;
+ /* the DBusPyConnection will close it now */
+ conn = NULL;
+
+ if (self->has_mainloop
+ && !dbus_py_set_up_connection((PyObject *)self, mainloop)) {
+ goto err;
+ }
+
+ Py_DECREF(mainloop);
+
+ DBG("%s() -> %p", __func__, self);
+ TRACE(self);
+ return (PyObject *)self;
+
+err:
+ DBG("Failed to construct Connection from DBusConnection at %p", conn);
+ Py_XDECREF(mainloop);
+ Py_XDECREF(self);
+ Py_XDECREF(ref);
+ if (conn) {
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_close(conn);
+ dbus_connection_unref(conn);
+ Py_END_ALLOW_THREADS
+ }
+ DBG("%s() fail", __func__);
+ DBG_WHEREAMI;
+ return NULL;
+}
+
+/* Connection type-methods ========================================== */
+
+/* Constructor */
+static PyObject *
+Connection_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ DBusConnection *conn;
+ const char *address;
+ PyObject *address_or_conn;
+ DBusError error;
+ PyObject *self, *mainloop = NULL;
+ static char *argnames[] = {"address", "mainloop", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", argnames,
+ &address_or_conn, &mainloop)) {
+ return NULL;
+ }
+
+ if (DBusPyLibDBusConnection_CheckExact(address_or_conn)) {
+ DBusPyLibDBusConnection *wrapper =
+ (DBusPyLibDBusConnection *) address_or_conn;
+
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(wrapper->conn);
+
+ conn = dbus_connection_ref (wrapper->conn);
+ }
+ else if ((address = PyString_AsString(address_or_conn)) != NULL) {
+ dbus_error_init(&error);
+
+ /* We always open a private connection (at the libdbus level). Sharing
+ * is done in Python, to keep things simple. */
+ Py_BEGIN_ALLOW_THREADS
+ conn = dbus_connection_open_private(address, &error);
+ Py_END_ALLOW_THREADS
+
+ if (!conn) {
+ DBusPyException_ConsumeError(&error);
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+
+ self = DBusPyConnection_NewConsumingDBusConnection(cls, conn, mainloop);
+ TRACE(self);
+
+ return self;
+}
+
+/* Post-construction: nothing to do (but don't chain up to object.__init__,
+ * which takes no arguments and does nothing) */
+static int
+Connection_tp_init(PyObject *self UNUSED, PyObject *args UNUSED,
+ PyObject *kwargs UNUSED)
+{
+ return 0;
+}
+
+/* Destructor */
+static void Connection_tp_dealloc(Connection *self)
+{
+ DBusConnection *conn = self->conn;
+ PyObject *et, *ev, *etb;
+ PyObject *filters = self->filters;
+ PyObject *object_paths = self->object_paths;
+
+ /* avoid clobbering any pending exception */
+ PyErr_Fetch(&et, &ev, &etb);
+
+ if (self->weaklist) {
+ PyObject_ClearWeakRefs((PyObject *)self);
+ }
+
+ TRACE(self);
+ DBG("Deallocating Connection at %p (DBusConnection at %p)", self, conn);
+ DBG_WHEREAMI;
+
+ DBG("Connection at %p: deleting callbacks", self);
+ self->filters = NULL;
+ Py_XDECREF(filters);
+ self->object_paths = NULL;
+ Py_XDECREF(object_paths);
+
+ if (conn) {
+ /* Might trigger callbacks if we're unlucky... */
+ DBG("Connection at %p has a conn, closing it...", self);
+ Py_BEGIN_ALLOW_THREADS
+ dbus_connection_close(conn);
+ Py_END_ALLOW_THREADS
+ }
+
+ /* make sure to do this last to preserve the invariant that
+ * self->conn is always non-NULL for any referenced Connection
+ * (until the filters and object paths were freed, we might have been
+ * in a reference cycle!)
+ */
+ DBG("Connection at %p: nulling self->conn", self);
+ self->conn = NULL;
+
+ if (conn) {
+ DBG("Connection at %p: unreffing conn", self);
+ dbus_connection_unref(conn);
+ }
+
+ DBG("Connection at %p: freeing self", self);
+ PyErr_Restore(et, ev, etb);
+ (self->ob_type->tp_free)((PyObject *)self);
+}
+
+/* Connection type object =========================================== */
+
+PyTypeObject DBusPyConnection_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_dbus_bindings.Connection", /*tp_name*/
+ sizeof(Connection), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)Connection_tp_dealloc,
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE,
+ Connection_tp_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ offsetof(Connection, weaklist), /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBusPyConnection_tp_methods, /*tp_methods*/
+ 0, /*tp_members*/
+ 0, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ Connection_tp_init, /*tp_init*/
+ 0, /*tp_alloc*/
+ Connection_tp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
+};
+
+dbus_bool_t
+dbus_py_init_conn_types(void)
+{
+ /* Get a slot to store our weakref on DBus Connections */
+ _connection_python_slot = -1;
+ if (!dbus_connection_allocate_data_slot(&_connection_python_slot))
+ return FALSE;
+ if (PyType_Ready(&DBusPyConnection_Type) < 0)
+ return FALSE;
+ return TRUE;
+}
+
+dbus_bool_t
+dbus_py_insert_conn_types(PyObject *this_module)
+{
+ if (PyModule_AddObject(this_module, "Connection",
+ (PyObject *)&DBusPyConnection_Type) < 0) return FALSE;
+ return TRUE;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/containers.c b/_dbus_bindings/containers.c
new file mode 100644
index 0000000..319ebe1
--- /dev/null
+++ b/_dbus_bindings/containers.c
@@ -0,0 +1,769 @@
+/* D-Bus container types: Array, Dict and Struct.
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+#include "types-internal.h"
+
+/* Array ============================================================ */
+
+PyDoc_STRVAR(Array_tp_doc,
+"An array of similar items, implemented as a subtype of list.\n"
+"\n"
+"As currently implemented, an Array behaves just like a list, but\n"
+"with the addition of a ``signature`` property set by the constructor;\n"
+"conversion of its items to D-Bus types is only done when it's sent in\n"
+"a Message. This might change in future so validation is done earlier.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Array([iterable][, signature][, variant_level])\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+"``signature`` is the D-Bus signature string for a single element of the\n"
+"array, or None. If not None it must represent a single complete type, the\n"
+"type of a single array item; the signature of the whole Array may be\n"
+"obtained by prepending ``a`` to the given signature.\n"
+"\n"
+"If None (the default), when the Array is sent over\n"
+"D-Bus, the item signature will be guessed from the first element.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an array, this is represented in Python by an\n"
+" Array with variant_level==2.\n"
+);
+
+static struct PyMemberDef Array_tp_members[] = {
+ {"signature", T_OBJECT, offsetof(DBusPyArray, signature), READONLY,
+ "The D-Bus signature of each element of this Array (a Signature "
+ "instance)"},
+ {"variant_level", T_LONG, offsetof(DBusPyArray, variant_level),
+ READONLY,
+ "The number of nested variants wrapping the real data. "
+ "0 if not in a variant."},
+ {NULL},
+};
+
+static void
+Array_tp_dealloc (DBusPyArray *self)
+{
+ Py_XDECREF(self->signature);
+ self->signature = NULL;
+ (PyList_Type.tp_dealloc)((PyObject *)self);
+}
+
+static PyObject *
+Array_tp_repr(DBusPyArray *self)
+{
+ PyObject *parent_repr = (PyList_Type.tp_repr)((PyObject *)self);
+ PyObject *sig_repr = PyObject_Repr(self->signature);
+ PyObject *my_repr = NULL;
+ long variant_level = self->variant_level;
+
+ if (!parent_repr) goto finally;
+ if (!sig_repr) goto finally;
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s, "
+ "variant_level=%ld)",
+ self->super.ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s)",
+ self->super.ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr));
+ }
+finally:
+ Py_XDECREF(parent_repr);
+ Py_XDECREF(sig_repr);
+ return my_repr;
+}
+
+static PyObject *
+Array_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *variant_level = NULL;
+ DBusPyArray *self = (DBusPyArray *)(PyList_Type.tp_new)(cls, args, kwargs);
+
+ /* variant_level is immutable, so handle it in __new__ rather than
+ __init__ */
+ if (!self) return NULL;
+ Py_INCREF(Py_None);
+ self->signature = Py_None;
+ self->variant_level = 0;
+ if (kwargs) {
+ variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
+ }
+ if (variant_level) {
+ self->variant_level = PyInt_AsLong(variant_level);
+ if (PyErr_Occurred()) {
+ Py_DECREF((PyObject *)self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+static int
+Array_tp_init (DBusPyArray *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *obj = dbus_py_empty_tuple;
+ PyObject *signature = NULL;
+ PyObject *tuple;
+ PyObject *variant_level;
+ /* variant_level is accepted but ignored - it's immutable, so
+ * __new__ handles it */
+ static char *argnames[] = {"iterable", "signature", "variant_level", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
+ &obj, &signature, &variant_level)) {
+ return -1;
+ }
+
+ /* convert signature from a borrowed ref of unknown type to an owned ref
+ of type Signature (or None) */
+ if (!signature) signature = Py_None;
+ if (signature == Py_None
+ || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
+ Py_INCREF(signature);
+ }
+ else {
+ signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
+ "(O)", signature);
+ if (!signature) return -1;
+ }
+
+ if (signature != Py_None) {
+ const char *c_str = PyString_AS_STRING(signature);
+
+ if (!dbus_signature_validate_single(c_str, NULL)) {
+ Py_DECREF(signature);
+ PyErr_SetString(PyExc_ValueError,
+ "There must be exactly one complete type in "
+ "an Array's signature parameter");
+ return -1;
+ }
+ }
+
+ tuple = Py_BuildValue("(O)", obj);
+ if (!tuple) {
+ Py_DECREF(signature);
+ return -1;
+ }
+ if ((PyList_Type.tp_init)((PyObject *)self, tuple, NULL) < 0) {
+ Py_DECREF(tuple);
+ Py_DECREF(signature);
+ return -1;
+ }
+ Py_DECREF(tuple);
+
+ Py_XDECREF(self->signature);
+ self->signature = signature;
+ return 0;
+}
+
+PyTypeObject DBusPyArray_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Array",
+ sizeof(DBusPyArray),
+ 0,
+ (destructor)Array_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)Array_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Array_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ Array_tp_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Array_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ Array_tp_new, /* tp_new */
+};
+
+/* Dict ============================================================= */
+
+PyDoc_STRVAR(Dict_tp_doc,
+"An mapping whose keys are similar and whose values are similar,\n"
+"implemented as a subtype of dict.\n"
+"\n"
+"As currently implemented, a Dictionary behaves just like a dict, but\n"
+"with the addition of a ``signature`` property set by the constructor;\n"
+"conversion of its items to D-Bus types is only done when it's sent in\n"
+"a Message. This may change in future so validation is done earlier.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" Dictionary(mapping_or_iterable=(), signature=None, variant_level=0)\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+"``signature`` is either a string or None. If a string, it must consist\n"
+"of exactly two complete type signatures, representing the 'key' type\n"
+"(which must be a primitive type, i.e. one of \"bdginoqstuxy\")\n"
+"and the 'value' type. The signature of the whole Dictionary will be\n"
+"``a{xx}`` where ``xx`` is replaced by the given signature.\n"
+"\n"
+"If it is None (the default), when the Dictionary is sent over\n"
+"D-Bus, the key and value signatures will be guessed from an arbitrary\n"
+"element of the Dictionary.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an array of DICT_ENTRY, this is represented in\n"
+" Python by a Dictionary with variant_level==2.\n"
+);
+
+static struct PyMemberDef Dict_tp_members[] = {
+ {"signature", T_OBJECT, offsetof(DBusPyDict, signature), READONLY,
+ "The D-Bus signature of each key in this Dictionary, followed by "
+ "that of each value in this Dictionary, as a Signature instance."},
+ {"variant_level", T_LONG, offsetof(DBusPyDict, variant_level),
+ READONLY,
+ "The number of nested variants wrapping the real data. "
+ "0 if not in a variant."},
+ {NULL},
+};
+
+static void
+Dict_tp_dealloc (DBusPyDict *self)
+{
+ Py_XDECREF(self->signature);
+ self->signature = NULL;
+ (PyDict_Type.tp_dealloc)((PyObject *)self);
+}
+
+static PyObject *
+Dict_tp_repr(DBusPyDict *self)
+{
+ PyObject *parent_repr = (PyDict_Type.tp_repr)((PyObject *)self);
+ PyObject *sig_repr = PyObject_Repr(self->signature);
+ PyObject *my_repr = NULL;
+ long variant_level = self->variant_level;
+
+ if (!parent_repr) goto finally;
+ if (!sig_repr) goto finally;
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s, "
+ "variant_level=%ld)",
+ self->super.ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s)",
+ self->super.ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr));
+ }
+finally:
+ Py_XDECREF(parent_repr);
+ Py_XDECREF(sig_repr);
+ return my_repr;
+}
+
+static PyObject *
+Dict_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ DBusPyDict *self = (DBusPyDict *)(PyDict_Type.tp_new)(cls, args, kwargs);
+ PyObject *variant_level = NULL;
+
+ /* variant_level is immutable, so handle it in __new__ rather than
+ __init__ */
+ if (!self) return NULL;
+ Py_INCREF(Py_None);
+ self->signature = Py_None;
+ self->variant_level = 0;
+ if (kwargs) {
+ variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
+ }
+ if (variant_level) {
+ self->variant_level = PyInt_AsLong(variant_level);
+ if (PyErr_Occurred()) {
+ Py_DECREF((PyObject *)self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+static int
+Dict_tp_init(DBusPyDict *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *obj = dbus_py_empty_tuple;
+ PyObject *signature = NULL;
+ PyObject *tuple;
+ PyObject *variant_level; /* ignored here - __new__ uses it */
+ static char *argnames[] = {"mapping_or_iterable", "signature",
+ "variant_level", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
+ &obj, &signature, &variant_level)) {
+ return -1;
+ }
+
+ /* convert signature from a borrowed ref of unknown type to an owned ref
+ of type Signature (or None) */
+ if (!signature) signature = Py_None;
+ if (signature == Py_None
+ || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
+ Py_INCREF(signature);
+ }
+ else {
+ signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
+ "(O)", signature);
+ if (!signature) return -1;
+ }
+
+ if (signature != Py_None) {
+ const char *c_str = PyString_AS_STRING(signature);
+
+ switch (c_str[0]) {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+#ifdef WITH_DBUS_FLOAT32
+ case DBUS_TYPE_FLOAT:
+#endif
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ break;
+ default:
+ Py_DECREF(signature);
+ PyErr_SetString(PyExc_ValueError,
+ "The key type in a Dictionary's signature "
+ "must be a primitive type");
+ return -1;
+ }
+
+ if (!dbus_signature_validate_single(c_str + 1, NULL)) {
+ Py_DECREF(signature);
+ PyErr_SetString(PyExc_ValueError,
+ "There must be exactly two complete types in "
+ "a Dictionary's signature parameter");
+ return -1;
+ }
+ }
+
+ tuple = Py_BuildValue("(O)", obj);
+ if (!tuple) {
+ Py_DECREF(signature);
+ return -1;
+ }
+
+ if ((PyDict_Type.tp_init((PyObject *)self, tuple, NULL)) < 0) {
+ Py_DECREF(tuple);
+ Py_DECREF(signature);
+ return -1;
+ }
+ Py_DECREF(tuple);
+
+ Py_XDECREF(self->signature);
+ self->signature = signature;
+ return 0;
+}
+
+PyTypeObject DBusPyDict_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Dictionary",
+ sizeof(DBusPyDict),
+ 0,
+ (destructor)Dict_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)Dict_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Dict_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ Dict_tp_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Dict_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ Dict_tp_new, /* tp_new */
+};
+
+/* Struct =========================================================== */
+
+static PyObject *struct_signatures;
+
+PyDoc_STRVAR(Struct_tp_doc,
+"An structure containing items of possibly distinct types.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Struct(iterable, signature=None, variant_level=0) -> Struct\n"
+"\n"
+"D-Bus structs may not be empty, so the iterable argument is required and\n"
+"may not be an empty iterable.\n"
+"\n"
+"``signature`` is either None, or a string representing the contents of the\n"
+"struct as one or more complete type signatures. The overall signature of\n"
+"the struct will be the given signature enclosed in parentheses, ``()``.\n"
+"\n"
+"If the signature is None (default) it will be guessed\n"
+"from the types of the items during construction.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a struct, this is represented in Python by a\n"
+" Struct with variant_level==2.\n"
+);
+
+static PyObject *
+Struct_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyTuple_Type.tp_repr)((PyObject *)self);
+ PyObject *sig;
+ PyObject *sig_repr = NULL;
+ PyObject *key;
+ long variant_level;
+ PyObject *my_repr = NULL;
+
+ if (!parent_repr) goto finally;
+ key = PyLong_FromVoidPtr(self);
+ if (!key) goto finally;
+ sig = PyDict_GetItem(struct_signatures, key);
+ Py_DECREF(key);
+ if (!sig) sig = Py_None;
+ sig_repr = PyObject_Repr(sig);
+ if (!sig_repr) goto finally;
+ variant_level = dbus_py_variant_level_get(self);
+ if (variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s, "
+ "variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr),
+ variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s, signature=%s)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ PyString_AS_STRING(sig_repr));
+ }
+
+finally:
+ Py_XDECREF(parent_repr);
+ Py_XDECREF(sig_repr);
+ return my_repr;
+}
+
+static PyObject *
+Struct_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *signature = NULL;
+ long variantness = 0;
+ PyObject *self, *key;
+ static char *argnames[] = {"signature", "variant_level", NULL};
+
+ if (PyTuple_Size(args) != 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes exactly one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|Ol:__new__", argnames,
+ &signature, &variantness)) {
+ return NULL;
+ }
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+
+ self = (PyTuple_Type.tp_new)(cls, args, NULL);
+ if (!self)
+ return NULL;
+ if (PyTuple_Size(self) < 1) {
+ PyErr_SetString(PyExc_ValueError, "D-Bus structs may not be empty");
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ if (!dbus_py_variant_level_set(self, variantness)) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ /* convert signature from a borrowed ref of unknown type to an owned ref
+ of type Signature (or None) */
+ if (!signature) signature = Py_None;
+ if (signature == Py_None
+ || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
+ Py_INCREF(signature);
+ }
+ else {
+ signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
+ "(O)", signature);
+ if (!signature) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ key = PyLong_FromVoidPtr(self);
+ if (!key) {
+ Py_DECREF(self);
+ Py_DECREF(signature);
+ return NULL;
+ }
+ if (PyDict_SetItem(struct_signatures, key, signature) < 0) {
+ Py_DECREF(key);
+ Py_DECREF(self);
+ Py_DECREF(signature);
+ return NULL;
+ }
+
+ Py_DECREF(key);
+ Py_DECREF(signature);
+ return self;
+}
+
+static void
+Struct_tp_dealloc(PyObject *self)
+{
+ PyObject *et, *ev, *etb, *key;
+
+ dbus_py_variant_level_clear(self);
+ PyErr_Fetch(&et, &ev, &etb);
+
+ key = PyLong_FromVoidPtr(self);
+ if (key) {
+ if (PyDict_GetItem(struct_signatures, key)) {
+ if (PyDict_DelItem(struct_signatures, key) < 0) {
+ /* should never happen */
+ PyErr_WriteUnraisable(self);
+ }
+ }
+ Py_DECREF(key);
+ }
+ else {
+ /* not enough memory to free all the memory... leak the signature,
+ * there's not much else we could do here */
+ PyErr_WriteUnraisable(self);
+ }
+
+ PyErr_Restore(et, ev, etb);
+ (PyTuple_Type.tp_dealloc)(self);
+}
+
+static PyObject *
+Struct_tp_getattro(PyObject *obj, PyObject *name)
+{
+ PyObject *key, *value;
+
+ if (PyString_Check(name)) {
+ Py_INCREF(name);
+ }
+ else if (PyUnicode_Check(name)) {
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);
+ if (!name) {
+ return NULL;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "attribute name must be string");
+ return NULL;
+ }
+
+ if (strcmp(PyString_AS_STRING(name), "signature")) {
+ value = dbus_py_variant_level_getattro(obj, name);
+ Py_DECREF(name);
+ return value;
+ }
+
+ Py_DECREF(name);
+
+ key = PyLong_FromVoidPtr(obj);
+
+ if (!key) {
+ return NULL;
+ }
+
+ value = PyDict_GetItem(struct_signatures, key);
+ Py_DECREF(key);
+
+ if (!value)
+ value = Py_None;
+ Py_INCREF(value);
+ return value;
+}
+
+PyTypeObject DBusPyStruct_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Struct",
+ 0,
+ 0,
+ Struct_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)Struct_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ Struct_tp_getattro, /* tp_getattro */
+ dbus_py_immutable_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Struct_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Struct_tp_new, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_container_types(void)
+{
+ struct_signatures = PyDict_New();
+ if (!struct_signatures) return 0;
+
+ DBusPyArray_Type.tp_base = &PyList_Type;
+ if (PyType_Ready(&DBusPyArray_Type) < 0) return 0;
+ DBusPyArray_Type.tp_print = NULL;
+
+ DBusPyDict_Type.tp_base = &PyDict_Type;
+ if (PyType_Ready(&DBusPyDict_Type) < 0) return 0;
+ DBusPyDict_Type.tp_print = NULL;
+
+ DBusPyStruct_Type.tp_base = &PyTuple_Type;
+ if (PyType_Ready(&DBusPyStruct_Type) < 0) return 0;
+ DBusPyStruct_Type.tp_print = NULL;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_container_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyArray_Type);
+ if (PyModule_AddObject(this_module, "Array",
+ (PyObject *)&DBusPyArray_Type) < 0) return 0;
+
+ Py_INCREF(&DBusPyDict_Type);
+ if (PyModule_AddObject(this_module, "Dictionary",
+ (PyObject *)&DBusPyDict_Type) < 0) return 0;
+
+ Py_INCREF(&DBusPyStruct_Type);
+ if (PyModule_AddObject(this_module, "Struct",
+ (PyObject *)&DBusPyStruct_Type) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
+
diff --git a/_dbus_bindings/dbus_bindings-internal.h b/_dbus_bindings/dbus_bindings-internal.h
new file mode 100644
index 0000000..e2b7fbe
--- /dev/null
+++ b/_dbus_bindings/dbus_bindings-internal.h
@@ -0,0 +1,245 @@
+/* _dbus_bindings internal API. For use within _dbus_bindings only.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DBUS_BINDINGS_INTERNAL_H
+#define DBUS_BINDINGS_INTERNAL_H
+
+#define PY_SSIZE_T_CLEAN 1
+
+#include <Python.h>
+
+/* Python < 2.5 compat */
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+#define INSIDE_DBUS_PYTHON_BINDINGS
+#include "dbus-python.h"
+
+/* no need for extern "C", this is only for internal use */
+
+/* on/off switch for debugging support (see below) */
+#undef USING_DBG
+#if 0 && !defined(DBG_IS_TOO_VERBOSE)
+# define USING_DBG 1
+#endif
+
+#define DEFINE_CHECK(type) \
+static inline int type##_Check (PyObject *o) \
+{ \
+ return (PyObject_TypeCheck (o, &type##_Type)); \
+} \
+static inline int type##_CheckExact (PyObject *o) \
+{ \
+ return ((o)->ob_type == &type##_Type); \
+}
+
+PyMODINIT_FUNC init_dbus_bindings(void);
+
+/* conn.c */
+extern PyTypeObject DBusPyConnection_Type;
+DEFINE_CHECK(DBusPyConnection)
+extern dbus_bool_t dbus_py_init_conn_types(void);
+extern dbus_bool_t dbus_py_insert_conn_types(PyObject *this_module);
+
+/* libdbusconn.c */
+extern PyTypeObject DBusPyLibDBusConnection_Type;
+DEFINE_CHECK(DBusPyLibDBusConnection)
+PyObject *DBusPyLibDBusConnection_New(DBusConnection *conn);
+extern dbus_bool_t dbus_py_init_libdbus_conn_types(void);
+extern dbus_bool_t dbus_py_insert_libdbus_conn_types(PyObject *this_module);
+
+/* bus.c */
+extern dbus_bool_t dbus_py_init_bus_types(void);
+extern dbus_bool_t dbus_py_insert_bus_types(PyObject *this_module);
+
+/* exceptions.c */
+extern PyObject *DBusPyException_SetString(const char *msg);
+extern PyObject *DBusPyException_ConsumeError(DBusError *error);
+extern dbus_bool_t dbus_py_init_exception_types(void);
+extern dbus_bool_t dbus_py_insert_exception_types(PyObject *this_module);
+
+/* types */
+extern PyTypeObject DBusPyBoolean_Type;
+DEFINE_CHECK(DBusPyBoolean)
+extern PyTypeObject DBusPyObjectPath_Type, DBusPySignature_Type;
+DEFINE_CHECK(DBusPyObjectPath)
+DEFINE_CHECK(DBusPySignature)
+extern PyTypeObject DBusPyArray_Type, DBusPyDict_Type, DBusPyStruct_Type;
+DEFINE_CHECK(DBusPyArray)
+DEFINE_CHECK(DBusPyDict)
+DEFINE_CHECK(DBusPyStruct)
+extern PyTypeObject DBusPyByte_Type, DBusPyByteArray_Type;
+DEFINE_CHECK(DBusPyByteArray)
+DEFINE_CHECK(DBusPyByte)
+extern PyTypeObject DBusPyUTF8String_Type, DBusPyString_Type;
+DEFINE_CHECK(DBusPyUTF8String)
+DEFINE_CHECK(DBusPyString)
+extern PyTypeObject DBusPyDouble_Type;
+DEFINE_CHECK(DBusPyDouble)
+extern PyTypeObject DBusPyInt16_Type, DBusPyUInt16_Type;
+DEFINE_CHECK(DBusPyInt16)
+DEFINE_CHECK(DBusPyUInt16)
+extern PyTypeObject DBusPyInt32_Type, DBusPyUInt32_Type;
+DEFINE_CHECK(DBusPyInt32)
+DEFINE_CHECK(DBusPyUInt32)
+extern PyTypeObject DBusPyInt64_Type, DBusPyUInt64_Type;
+DEFINE_CHECK(DBusPyInt64)
+DEFINE_CHECK(DBusPyUInt64)
+extern dbus_bool_t dbus_py_init_abstract(void);
+extern dbus_bool_t dbus_py_init_signature(void);
+extern dbus_bool_t dbus_py_init_int_types(void);
+extern dbus_bool_t dbus_py_init_string_types(void);
+extern dbus_bool_t dbus_py_init_float_types(void);
+extern dbus_bool_t dbus_py_init_container_types(void);
+extern dbus_bool_t dbus_py_init_byte_types(void);
+extern dbus_bool_t dbus_py_insert_abstract_types(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_signature(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_int_types(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_string_types(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_float_types(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_container_types(PyObject *this_module);
+extern dbus_bool_t dbus_py_insert_byte_types(PyObject *this_module);
+
+/* generic */
+extern void dbus_py_take_gil_and_xdecref(PyObject *);
+extern int dbus_py_immutable_setattro(PyObject *, PyObject *, PyObject *);
+extern PyObject *dbus_py_tp_richcompare_by_pointer(PyObject *,
+ PyObject *,
+ int);
+extern long dbus_py_tp_hash_by_pointer(PyObject *self);
+extern PyObject *dbus_py_empty_tuple;
+extern dbus_bool_t dbus_py_init_generic(void);
+
+/* message.c */
+extern DBusMessage *DBusPyMessage_BorrowDBusMessage(PyObject *msg);
+extern PyObject *DBusPyMessage_ConsumeDBusMessage(DBusMessage *);
+extern dbus_bool_t dbus_py_init_message_types(void);
+extern dbus_bool_t dbus_py_insert_message_types(PyObject *this_module);
+
+/* pending-call.c */
+extern PyObject *DBusPyPendingCall_ConsumeDBusPendingCall(DBusPendingCall *,
+ PyObject *);
+extern dbus_bool_t dbus_py_init_pending_call(void);
+extern dbus_bool_t dbus_py_insert_pending_call(PyObject *this_module);
+
+/* mainloop.c */
+extern dbus_bool_t dbus_py_set_up_connection(PyObject *conn,
+ PyObject *mainloop);
+extern dbus_bool_t dbus_py_set_up_server(PyObject *server,
+ PyObject *mainloop);
+extern PyObject *dbus_py_get_default_main_loop(void);
+extern dbus_bool_t dbus_py_check_mainloop_sanity(PyObject *);
+extern dbus_bool_t dbus_py_init_mainloop(void);
+extern dbus_bool_t dbus_py_insert_mainloop_types(PyObject *);
+
+/* server.c */
+extern PyTypeObject DBusPyServer_Type;
+DEFINE_CHECK(DBusPyServer)
+extern dbus_bool_t dbus_py_init_server_types(void);
+extern dbus_bool_t dbus_py_insert_server_types(PyObject *this_module);
+extern DBusServer *DBusPyServer_BorrowDBusServer(PyObject *self);
+
+/* validation.c */
+dbus_bool_t dbus_py_validate_bus_name(const char *name,
+ dbus_bool_t may_be_unique,
+ dbus_bool_t may_be_not_unique);
+dbus_bool_t dbus_py_validate_member_name(const char *name);
+dbus_bool_t dbus_py_validate_interface_name(const char *name);
+dbus_bool_t dbus_py_validate_object_path(const char *path);
+#define dbus_py_validate_error_name dbus_py_validate_interface_name
+
+/* debugging support */
+void _dbus_py_assertion_failed(const char *);
+#define DBUS_PY_RAISE_VIA_NULL_IF_FAIL(assertion) \
+ do { if (!(assertion)) { \
+ _dbus_py_assertion_failed(#assertion); \
+ return NULL; \
+ } \
+ } while (0)
+
+#define DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(assertion, label) \
+ do { if (!(assertion)) { \
+ _dbus_py_assertion_failed(#assertion); \
+ goto label; \
+ } \
+ } while (0)
+
+#define DBUS_PY_RAISE_VIA_RETURN_IF_FAIL(assertion, value) \
+ do { if (!(assertion)) { \
+ _dbus_py_assertion_failed(#assertion); \
+ return value; \
+ } \
+ } while (0)
+
+/* verbose debugging support */
+#ifdef USING_DBG
+
+# include <sys/types.h>
+# include <unistd.h>
+
+void _dbus_py_dbg_exc(void);
+void _dbus_py_whereami(void);
+void _dbus_py_dbg_dump_message(DBusMessage *);
+
+# define TRACE(self) do { fprintf(stderr, "TRACE: <%s at %p> in %s, " \
+ "%d refs\n", \
+ self->ob_type->tp_name, \
+ self, __func__, \
+ self->ob_refcnt); } while (0)
+# define DBG(format, ...) fprintf(stderr, "DEBUG: " format "\n",\
+ __VA_ARGS__)
+# define DBG_EXC(format, ...) do {DBG(format, __VA_ARGS__); \
+ _dbus_py_dbg_exc();} while (0)
+# define DBG_DUMP_MESSAGE(x) _dbus_py_dbg_dump_message(x)
+# define DBG_WHEREAMI _dbus_py_whereami()
+
+#else /* !defined(USING_DBG) */
+
+# define TRACE(self) do {} while (0)
+# define DBG(format, ...) do {} while (0)
+# define DBG_EXC(format, ...) do {} while (0)
+# define DBG_DUMP_MESSAGE(x) do {} while (0)
+# define DBG_WHEREAMI do {} while (0)
+
+#endif /* !defined(USING_DBG) */
+
+/* General-purpose Python glue */
+
+#define DEFERRED_ADDRESS(ADDR) 0
+
+#if defined(__GNUC__)
+# if __GNUC__ >= 3
+# define UNUSED __attribute__((__unused__))
+# else
+# define UNUSED /*nothing*/
+# endif
+#else
+# define UNUSED /*nothing*/
+#endif
+
+#endif
diff --git a/_dbus_bindings/debug.c b/_dbus_bindings/debug.c
new file mode 100644
index 0000000..b347628
--- /dev/null
+++ b/_dbus_bindings/debug.c
@@ -0,0 +1,95 @@
+/* Debug code for _dbus_bindings.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include <stdlib.h>
+
+void
+_dbus_py_assertion_failed(const char *assertion)
+{
+ PyErr_SetString(PyExc_AssertionError, assertion);
+#if 1 || defined(USING_DBG) || defined(FATAL_ASSERTIONS)
+ /* print the Python stack, and dump core so we can see the C stack too */
+ PyErr_Print();
+ abort();
+#endif
+}
+
+#ifdef USING_DBG
+void
+_dbus_py_whereami(void)
+{
+ PyObject *c, *v, *t;
+ /* This is a little mad. We want to get the traceback without
+ clearing the error indicator, if any. */
+ PyErr_Fetch(&c, &v, &t); /* 3 new refs */
+ Py_XINCREF(c); Py_XINCREF(v); Py_XINCREF(t); /* now we own 6 refs */
+ PyErr_Restore(c, v, t); /* steals 3 refs */
+
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_AssertionError,
+ "No error, but plz provide traceback kthx");
+ }
+ PyErr_Print();
+
+ PyErr_Restore(c, v, t); /* steals another 3 refs */
+}
+
+void
+_dbus_py_dbg_exc(void)
+{
+ PyObject *c, *v, *t;
+ /* This is a little mad. We want to get the traceback without
+ clearing the error indicator. */
+ PyErr_Fetch(&c, &v, &t); /* 3 new refs */
+ Py_XINCREF(c); Py_XINCREF(v); Py_XINCREF(t); /* now we own 6 refs */
+ PyErr_Restore(c, v, t); /* steals 3 refs */
+ PyErr_Print();
+ PyErr_Restore(c, v, t); /* steals another 3 refs */
+}
+
+void
+_dbus_py_dbg_dump_message(DBusMessage *message)
+{
+ const char *s;
+ fprintf(stderr, "DBusMessage at %p\n", message);
+
+ s = dbus_message_get_destination(message);
+ if (!s) s = "(null)";
+ fprintf(stderr, "\tdestination %s\n", s);
+
+ s = dbus_message_get_interface(message);
+ if (!s) s = "(null)";
+ fprintf(stderr, "\tinterface %s\n", s);
+
+ s = dbus_message_get_member(message);
+ if (!s) s = "(null)";
+ fprintf(stderr, "\tmember %s\n", s);
+
+ s = dbus_message_get_path(message);
+ if (!s) s = "(null)";
+ fprintf(stderr, "\tpath %s\n", s);
+}
+#endif
diff --git a/_dbus_bindings/exceptions.c b/_dbus_bindings/exceptions.c
new file mode 100644
index 0000000..141ce9e
--- /dev/null
+++ b/_dbus_bindings/exceptions.c
@@ -0,0 +1,99 @@
+/* D-Bus exception base classes.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+
+static PyObject *imported_dbus_exception = NULL;
+
+static dbus_bool_t
+import_exception(void)
+{
+ PyObject *name;
+ PyObject *exceptions;
+
+ if (imported_dbus_exception != NULL) {
+ return TRUE;
+ }
+
+ name = PyString_FromString("dbus.exceptions");
+ if (name == NULL) {
+ return FALSE;
+ }
+ exceptions = PyImport_Import(name);
+ Py_DECREF(name);
+ if (exceptions == NULL) {
+ return FALSE;
+ }
+ imported_dbus_exception = PyObject_GetAttrString(exceptions,
+ "DBusException");
+ Py_DECREF(exceptions);
+
+ return (imported_dbus_exception != NULL);
+}
+
+PyObject *
+DBusPyException_SetString(const char *msg)
+{
+ if (imported_dbus_exception != NULL || import_exception()) {
+ PyErr_SetString(imported_dbus_exception, msg);
+ }
+ return NULL;
+}
+
+PyObject *
+DBusPyException_ConsumeError(DBusError *error)
+{
+ PyObject *exc_value = NULL;
+
+ if (imported_dbus_exception == NULL && !import_exception()) {
+ goto finally;
+ }
+
+ exc_value = PyObject_CallFunction(imported_dbus_exception,
+ "s",
+ error->message ? error->message
+ : "");
+ if (error->name) {
+ PyObject *name = PyString_FromString(error->name);
+ int ret;
+
+ if (!name)
+ goto finally;
+ ret = PyObject_SetAttrString(exc_value, "_dbus_error_name", name);
+ Py_DECREF(name);
+ if (ret < 0) {
+ goto finally;
+ }
+ }
+
+ PyErr_SetObject(imported_dbus_exception, exc_value);
+
+finally:
+ Py_XDECREF(exc_value);
+ dbus_error_free(error);
+ return NULL;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/float.c b/_dbus_bindings/float.c
new file mode 100644
index 0000000..5826ec3
--- /dev/null
+++ b/_dbus_bindings/float.c
@@ -0,0 +1,158 @@
+/* Simple D-Bus types: Double and (with appropriate #defines) Float
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+#include "types-internal.h"
+
+PyDoc_STRVAR(Double_tp_doc,
+"A double-precision floating point number (a subtype of float).");
+
+#ifdef WITH_DBUS_FLOAT32
+PyDoc_STRVAR(Float_tp_doc,
+"A single-precision floating point number (a subtype of float).");
+#endif
+
+PyTypeObject DBusPyDouble_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Double",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Double_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPythonFloatType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+#ifdef WITH_DBUS_FLOAT32
+
+PyTypeObject DBusPyFloat_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Float",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Float_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPythonFloatType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+#endif /* defined(WITH_DBUS_FLOAT32) */
+
+dbus_bool_t
+dbus_py_init_float_types(void)
+{
+ DBusPyDouble_Type.tp_base = &DBusPyFloatBase_Type;
+ if (PyType_Ready(&DBusPyDouble_Type) < 0) return 0;
+ DBusPyDouble_Type.tp_print = NULL;
+
+#ifdef WITH_DBUS_FLOAT32
+ DBusPyFloat_Type.tp_base = &DBusPyFloatBase_Type;
+ if (PyType_Ready(&DBusPyFloat_Type) < 0) return 0;
+ DBusPyFloat_Type.tp_print = NULL;
+#endif
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_float_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyDouble_Type);
+ if (PyModule_AddObject(this_module, "Double",
+ (PyObject *)&DBusPyDouble_Type) < 0) return 0;
+#ifdef WITH_DBUS_FLOAT32
+ Py_INCREF(&DBusPyFloat_Type);
+ if (PyModule_AddObject(this_module, "Float",
+ (PyObject *)&DBusPyFloat_Type) < 0) return 0;
+#endif
+
+ return 1;
+}
diff --git a/_dbus_bindings/generic.c b/_dbus_bindings/generic.c
new file mode 100644
index 0000000..cda138d
--- /dev/null
+++ b/_dbus_bindings/generic.c
@@ -0,0 +1,84 @@
+/* General Python glue code, used in _dbus_bindings but not actually anything
+ * to do with D-Bus.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+
+/* The empty tuple, held globally since dbus-python turns out to use it quite
+ * a lot
+ */
+PyObject *dbus_py_empty_tuple = NULL;
+
+PyObject *
+dbus_py_tp_richcompare_by_pointer(PyObject *self,
+ PyObject *other,
+ int op)
+{
+ if (op == Py_EQ || op == Py_NE) {
+ if (self == other) {
+ return PyInt_FromLong(op == Py_EQ);
+ }
+ return PyInt_FromLong(op == Py_NE);
+ }
+ PyErr_SetString(PyExc_TypeError,
+ "Instances of this type are not ordered");
+ return NULL;
+}
+
+long
+dbus_py_tp_hash_by_pointer(PyObject *self)
+{
+ long hash = (long)self;
+ return (hash == -1L ? -2L : hash);
+}
+
+int
+dbus_py_immutable_setattro(PyObject *obj UNUSED,
+ PyObject *name UNUSED,
+ PyObject *value UNUSED)
+{
+ PyErr_SetString(PyExc_AttributeError, "Object is immutable");
+ return -1;
+}
+
+/* Take the global interpreter lock and decrement the reference count.
+ * Suitable for calling from a C callback. */
+void
+dbus_py_take_gil_and_xdecref(PyObject *obj)
+{
+ PyGILState_STATE gil = PyGILState_Ensure();
+ Py_XDECREF(obj);
+ PyGILState_Release(gil);
+}
+
+dbus_bool_t
+dbus_py_init_generic(void)
+{
+ dbus_py_empty_tuple = PyTuple_New(0);
+ if (!dbus_py_empty_tuple) return 0;
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/int.c b/_dbus_bindings/int.c
new file mode 100644
index 0000000..b669d57
--- /dev/null
+++ b/_dbus_bindings/int.c
@@ -0,0 +1,779 @@
+/* Simple D-Bus types: integers of various sizes, and ObjectPath.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "types-internal.h"
+
+/* Specific types =================================================== */
+
+/* Boolean, a subclass of DBusPythonInt ============================= */
+
+PyDoc_STRVAR(Boolean_tp_doc,
+"A boolean, represented as a subtype of `int` (not `bool`, because `bool`\n"
+"cannot be subclassed).\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Boolean(value[, variant_level]) -> Boolean\n"
+"\n"
+"``value`` is converted to 0 or 1 as if by ``int(bool(value))``.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a boolean, this is represented in Python by a\n"
+" Boolean with variant_level==2.\n"
+);
+
+static PyObject *
+Boolean_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *tuple, *self, *value = Py_None;
+ long variantness = 0;
+ static char *argnames[] = {"_", "variant_level", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ol:__new__", argnames,
+ &value, &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+ tuple = Py_BuildValue("(i)", PyObject_IsTrue(value) ? 1 : 0);
+ if (!tuple) return NULL;
+ self = (DBusPyIntBase_Type.tp_new)(cls, tuple, kwargs);
+ Py_DECREF(tuple);
+ return self;
+}
+
+static PyObject *
+Boolean_tp_repr (PyObject *self)
+{
+ long variant_level = ((DBusPyIntBase *)self)->variant_level;
+ if (variant_level > 0) {
+ return PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyInt_AsLong(self) ? "True" : "False",
+ variant_level);
+ }
+ return PyString_FromFormat("%s(%s)",
+ self->ob_type->tp_name,
+ PyInt_AsLong(self) ? "True" : "False");
+}
+
+PyTypeObject DBusPyBoolean_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Boolean",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ Boolean_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Boolean_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Boolean_tp_new, /* tp_new */
+};
+
+/* Int16 ============================================================ */
+
+PyDoc_STRVAR(Int16_tp_doc,
+"A signed 16-bit integer between -0x8000 and +0x7FFF, represented as\n"
+"a subtype of `int`.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Int16(value: int[, variant_level: int]) -> Int16\n"
+"\n"
+"value must be within the allowed range, or OverflowError will be\n"
+"raised.\n"
+"\n"
+" variant_level must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an int16, this is represented in Python by an\n"
+" Int16 with variant_level==2.\n"
+);
+
+dbus_int16_t
+dbus_py_int16_range_check(PyObject *obj)
+{
+ long i = PyInt_AsLong (obj);
+ if (i == -1 && PyErr_Occurred ()) return -1;
+ if (i < -0x8000 || i > 0x7fff) {
+ PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int16",
+ (int)i);
+ return -1;
+ }
+ return i;
+}
+
+static PyObject *
+Int16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_int16_range_check(self) == -1 && PyErr_Occurred()) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ return self;
+}
+
+PyTypeObject DBusPyInt16_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Int16",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Int16_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Int16_tp_new, /* tp_new */
+};
+
+/* UInt16 =========================================================== */
+
+PyDoc_STRVAR(UInt16_tp_doc,
+"An unsigned 16-bit integer between 0 and 0xFFFF, represented as\n"
+"a subtype of `int`.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.UInt16(value: int[, variant_level: int]) -> UInt16\n"
+"\n"
+"``value`` must be within the allowed range, or `OverflowError` will be\n"
+"raised.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a uint16, this is represented in Python by a\n"
+" UInt16 with variant_level==2.\n"
+);
+
+dbus_uint16_t
+dbus_py_uint16_range_check(PyObject *obj)
+{
+ long i = PyInt_AsLong(obj);
+ if (i == -1 && PyErr_Occurred()) return (dbus_uint16_t)(-1);
+ if (i < 0 || i > 0xffff) {
+ PyErr_Format(PyExc_OverflowError, "Value %d out of range for UInt16",
+ (int)i);
+ return (dbus_uint16_t)(-1);
+ }
+ return i;
+}
+
+static PyObject *
+UInt16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_uint16_range_check(self) == (dbus_uint16_t)(-1)
+ && PyErr_Occurred()) {
+ Py_DECREF (self);
+ return NULL;
+ }
+ return self;
+}
+
+PyTypeObject DBusPyUInt16_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.UInt16",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UInt16_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ UInt16_tp_new, /* tp_new */
+};
+
+/* Int32 ============================================================ */
+
+PyDoc_STRVAR(Int32_tp_doc,
+"A signed 32-bit integer between -0x8000 0000 and +0x7FFF FFFF, represented as\n"
+"a subtype of `int`.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Int32(value: int[, variant_level: int]) -> Int32\n"
+"\n"
+"``value`` must be within the allowed range, or `OverflowError` will be\n"
+"raised.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an int32, this is represented in Python by an\n"
+" Int32 with variant_level==2.\n"
+);
+
+dbus_int32_t
+dbus_py_int32_range_check(PyObject *obj)
+{
+ long i = PyInt_AsLong(obj);
+ if (i == -1 && PyErr_Occurred()) return -1;
+ if (i < INT32_MIN || i > INT32_MAX) {
+ PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int32",
+ (int)i);
+ return -1;
+ }
+ return i;
+}
+
+static PyObject *
+Int32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_int32_range_check(self) == -1 && PyErr_Occurred()) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ return self;
+}
+
+PyTypeObject DBusPyInt32_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Int32",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Int32_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Int32_tp_new, /* tp_new */
+};
+
+/* UInt32 =========================================================== */
+
+PyDoc_STRVAR(UInt32_tp_doc,
+"An unsigned 32-bit integer between 0 and 0xFFFF FFFF, represented as a\n"
+"subtype of `long`.\n"
+"\n"
+"Note that this may be changed in future to be a subtype of `int` on\n"
+"64-bit platforms; applications should not rely on either behaviour.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.UInt32(value: long[, variant_level: int]) -> UInt32\n"
+"\n"
+"``value`` must be within the allowed range, or `OverflowError` will be\n"
+"raised.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a uint32, this is represented in Python by a\n"
+" UInt32 with variant_level==2.\n"
+);
+
+dbus_uint32_t
+dbus_py_uint32_range_check(PyObject *obj)
+{
+ unsigned long i;
+ PyObject *long_obj = PyNumber_Long(obj);
+
+ if (!long_obj) return (dbus_uint32_t)(-1);
+ i = PyLong_AsUnsignedLong(long_obj);
+ if (i == (unsigned long)(-1) && PyErr_Occurred()) {
+ Py_DECREF(long_obj);
+ return (dbus_uint32_t)(-1);
+ }
+ if (i > UINT32_MAX) {
+ PyErr_Format(PyExc_OverflowError, "Value %d out of range for UInt32",
+ (int)i);
+ Py_DECREF(long_obj);
+ return (dbus_uint32_t)(-1);
+ }
+ Py_DECREF(long_obj);
+ return i;
+}
+
+static PyObject *
+UInt32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_uint32_range_check(self) == (dbus_uint32_t)(-1)
+ && PyErr_Occurred()) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ return self;
+}
+
+PyTypeObject DBusPyUInt32_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.UInt32",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UInt32_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyLongBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ UInt32_tp_new, /* tp_new */
+};
+
+/* Int64 =========================================================== */
+
+PyDoc_STRVAR(Int64_tp_doc,
+"A signed 64-bit integer between -0x8000 0000 0000 0000 and\n"
+"+0x7FFF FFFF FFFF FFFF, represented as a subtype of `long`.\n"
+"\n"
+"Note that this may be changed in future to be a subtype of `int` on\n"
+"64-bit platforms; applications should not rely on either behaviour.\n"
+"\n"
+"This type only works on platforms where the C compiler has suitable\n"
+"64-bit types, such as C99 ``long long``.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.Int64(value: long[, variant_level: int]) -> Int64\n"
+"\n"
+"``value`` must be within the allowed range, or `OverflowError` will be\n"
+"raised.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an int64, this is represented in Python by an\n"
+" Int64 with variant_level==2.\n"
+);
+
+#ifdef DBUS_PYTHON_64_BIT_WORKS
+dbus_int64_t
+dbus_py_int64_range_check(PyObject *obj)
+{
+ PY_LONG_LONG i;
+ PyObject *long_obj = PyNumber_Long(obj);
+
+ if (!long_obj) return -1;
+ i = PyLong_AsLongLong(long_obj);
+ if (i == -1 && PyErr_Occurred()) {
+ Py_DECREF(long_obj);
+ return -1;
+ }
+ if (i < INT64_MIN || i > INT64_MAX) {
+ PyErr_SetString(PyExc_OverflowError, "Value out of range for Int64");
+ Py_DECREF(long_obj);
+ return -1;
+ }
+ Py_DECREF(long_obj);
+ return i;
+}
+#endif
+
+static PyObject *
+Int64_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+#ifdef DBUS_PYTHON_64_BIT_WORKS
+ PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_int64_range_check(self) == -1 && PyErr_Occurred()) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ return self;
+#else
+ PyErr_SetString(PyExc_NotImplementedError,
+ "64-bit types are not available on this platform");
+ return NULL;
+#endif
+}
+
+PyTypeObject DBusPyInt64_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Int64",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Int64_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyLongBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Int64_tp_new, /* tp_new */
+};
+
+/* UInt64 =========================================================== */
+
+PyDoc_STRVAR(UInt64_tp_doc,
+"An unsigned 64-bit integer between 0 and 0xFFFF FFFF FFFF FFFF,\n"
+"represented as a subtype of `long`.\n"
+"\n"
+"This type only exists on platforms where the C compiler has suitable\n"
+"64-bit types, such as C99 ``unsigned long long``.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.UInt64(value: long[, variant_level: int]) -> UInt64\n"
+"\n"
+"``value`` must be within the allowed range, or `OverflowError` will be\n"
+"raised.\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a uint64, this is represented in Python by a\n"
+" UInt64 with variant_level==2.\n"
+);
+
+dbus_uint64_t
+dbus_py_uint64_range_check(PyObject *obj)
+{
+ unsigned PY_LONG_LONG i;
+ PyObject *long_obj = PyNumber_Long(obj);
+
+ if (!long_obj) return (dbus_uint64_t)(-1);
+ i = PyLong_AsUnsignedLongLong(long_obj);
+ if (i == (unsigned PY_LONG_LONG)(-1) && PyErr_Occurred()) {
+ Py_DECREF(long_obj);
+ return (dbus_uint64_t)(-1);
+ }
+ if (i > UINT64_MAX) {
+ PyErr_SetString(PyExc_OverflowError, "Value out of range for UInt64");
+ Py_DECREF(long_obj);
+ return (dbus_uint64_t)(-1);
+ }
+ Py_DECREF(long_obj);
+ return i;
+}
+
+static PyObject *
+UInt64_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+#ifdef DBUS_PYTHON_64_BIT_WORKS
+ PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
+ if (self && dbus_py_uint64_range_check(self) == (dbus_uint64_t)(-1)
+ && PyErr_Occurred()) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ return self;
+#else
+ PyErr_SetString(PyExc_NotImplementedError,
+ "64-bit integer types are not supported on this platform");
+ return NULL;
+#endif
+}
+
+PyTypeObject DBusPyUInt64_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.UInt64",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UInt64_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyLongBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ UInt64_tp_new, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_int_types(void)
+{
+ DBusPyInt16_Type.tp_base = &DBusPyIntBase_Type;
+ if (PyType_Ready(&DBusPyInt16_Type) < 0) return 0;
+ /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
+ desired */
+ DBusPyInt16_Type.tp_print = NULL;
+
+ DBusPyUInt16_Type.tp_base = &DBusPyIntBase_Type;
+ if (PyType_Ready(&DBusPyUInt16_Type) < 0) return 0;
+ DBusPyUInt16_Type.tp_print = NULL;
+
+ DBusPyInt32_Type.tp_base = &DBusPyIntBase_Type;
+ if (PyType_Ready(&DBusPyInt32_Type) < 0) return 0;
+ DBusPyInt32_Type.tp_print = NULL;
+
+ DBusPyUInt32_Type.tp_base = &DBusPyLongBase_Type;
+ if (PyType_Ready(&DBusPyUInt32_Type) < 0) return 0;
+ DBusPyUInt32_Type.tp_print = NULL;
+
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+ DBusPyInt64_Type.tp_base = &DBusPyLongBase_Type;
+ if (PyType_Ready(&DBusPyInt64_Type) < 0) return 0;
+ DBusPyInt64_Type.tp_print = NULL;
+
+ DBusPyUInt64_Type.tp_base = &DBusPyLongBase_Type;
+ if (PyType_Ready(&DBusPyUInt64_Type) < 0) return 0;
+ DBusPyUInt64_Type.tp_print = NULL;
+#endif
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_int_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyInt16_Type);
+ Py_INCREF(&DBusPyUInt16_Type);
+ Py_INCREF(&DBusPyInt32_Type);
+ Py_INCREF(&DBusPyUInt32_Type);
+ Py_INCREF(&DBusPyInt64_Type);
+ Py_INCREF(&DBusPyUInt64_Type);
+ Py_INCREF(&DBusPyBoolean_Type);
+ if (PyModule_AddObject(this_module, "Int16",
+ (PyObject *)&DBusPyInt16_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "UInt16",
+ (PyObject *)&DBusPyUInt16_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "Int32",
+ (PyObject *)&DBusPyInt32_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "UInt32",
+ (PyObject *)&DBusPyUInt32_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "Int64",
+ (PyObject *)&DBusPyInt64_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "UInt64",
+ (PyObject *)&DBusPyUInt64_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "Boolean",
+ (PyObject *)&DBusPyBoolean_Type) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/libdbusconn.c b/_dbus_bindings/libdbusconn.c
new file mode 100644
index 0000000..9bd8def
--- /dev/null
+++ b/_dbus_bindings/libdbusconn.c
@@ -0,0 +1,124 @@
+/* An extremely thin wrapper around a libdbus Connection, for use by
+ * Server.
+ *
+ * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include "conn-internal.h"
+
+PyDoc_STRVAR(DBusPyLibDBusConnection_tp_doc,
+"A reference to a ``DBusConnection`` from ``libdbus``, which might not\n"
+"have been attached to a `dbus.connection.Connection` yet.\n"
+"\n"
+"Cannot be instantiated from Python. The only use of this object is to\n"
+"pass it to the ``dbus.connection.Connection`` constructor instead of an\n"
+"address.\n"
+);
+
+/** Create a DBusPyLibDBusConnection from a DBusConnection.
+ */
+PyObject *
+DBusPyLibDBusConnection_New(DBusConnection *conn)
+{
+ DBusPyLibDBusConnection *self = NULL;
+
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(conn);
+
+ self = (DBusPyLibDBusConnection *)(DBusPyLibDBusConnection_Type.tp_alloc(
+ &DBusPyLibDBusConnection_Type, 0));
+
+ if (!self)
+ return NULL;
+
+ self->conn = dbus_connection_ref (conn);
+
+ return (PyObject *)self;
+}
+
+/* Destructor */
+static void
+DBusPyLibDBusConnection_tp_dealloc(Connection *self)
+{
+ DBusConnection *conn = self->conn;
+ PyObject *et, *ev, *etb;
+
+ /* avoid clobbering any pending exception */
+ PyErr_Fetch(&et, &ev, &etb);
+
+ self->conn = NULL;
+
+ if (conn) {
+ dbus_connection_unref(conn);
+ }
+
+ PyErr_Restore(et, ev, etb);
+ (self->ob_type->tp_free)((PyObject *) self);
+}
+
+PyTypeObject DBusPyLibDBusConnection_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_dbus_bindings._LibDBusConnection",
+ sizeof(DBusPyLibDBusConnection),
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)DBusPyLibDBusConnection_tp_dealloc,
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT,
+ DBusPyLibDBusConnection_tp_doc,
+};
+
+dbus_bool_t
+dbus_py_init_libdbus_conn_types(void)
+{
+ if (PyType_Ready(&DBusPyLibDBusConnection_Type) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+dbus_bool_t
+dbus_py_insert_libdbus_conn_types(PyObject *this_module)
+{
+ if (PyModule_AddObject(this_module, "_LibDBusConnection",
+ (PyObject *)&DBusPyLibDBusConnection_Type) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/mainloop.c b/_dbus_bindings/mainloop.c
new file mode 100644
index 0000000..1733410
--- /dev/null
+++ b/_dbus_bindings/mainloop.c
@@ -0,0 +1,208 @@
+/* Implementation of main-loop integration for dbus-python.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008 Huang Peng <phuang@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "dbus_bindings-internal.h"
+
+/* Native mainloop wrapper ========================================= */
+
+PyDoc_STRVAR(NativeMainLoop_tp_doc,
+"Object representing D-Bus main loop integration done in native code.\n"
+"Cannot be instantiated directly.\n"
+);
+
+static PyTypeObject NativeMainLoop_Type;
+
+DEFINE_CHECK(NativeMainLoop)
+
+typedef struct {
+ PyObject_HEAD
+ /* Called with the GIL held, should set a Python exception on error */
+ dbus_bool_t (*set_up_connection_cb)(DBusConnection *, void *);
+ dbus_bool_t (*set_up_server_cb)(DBusServer *, void *);
+ /* Called in a destructor. Must not touch the exception state (use
+ * PyErr_Fetch and PyErr_Restore if necessary). */
+ void (*free_cb)(void *);
+ void *data;
+} NativeMainLoop;
+
+static void NativeMainLoop_tp_dealloc(NativeMainLoop *self)
+{
+ if (self->data && self->free_cb) {
+ (self->free_cb)(self->data);
+ }
+ PyObject_Del((PyObject *)self);
+}
+
+static PyTypeObject NativeMainLoop_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.mainloop.NativeMainLoop",
+ sizeof(NativeMainLoop),
+ 0,
+ (destructor)NativeMainLoop_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ NativeMainLoop_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ /* deliberately not callable! */
+ 0, /* tp_new */
+};
+
+/* Internal C API for Connection, Bus, Server ======================= */
+
+dbus_bool_t
+dbus_py_check_mainloop_sanity(PyObject *mainloop)
+{
+ if (NativeMainLoop_Check(mainloop)) {
+ return TRUE;
+ }
+ PyErr_SetString(PyExc_TypeError,
+ "A dbus.mainloop.NativeMainLoop instance is required");
+ return FALSE;
+}
+
+dbus_bool_t
+dbus_py_set_up_connection(PyObject *conn, PyObject *mainloop)
+{
+ if (NativeMainLoop_Check(mainloop)) {
+ /* Native mainloops are allowed to do arbitrary strange things */
+ NativeMainLoop *nml = (NativeMainLoop *)mainloop;
+ DBusConnection *dbc = DBusPyConnection_BorrowDBusConnection(conn);
+
+ if (!dbc) {
+ return FALSE;
+ }
+ return (nml->set_up_connection_cb)(dbc, nml->data);
+ }
+ PyErr_SetString(PyExc_TypeError,
+ "A dbus.mainloop.NativeMainLoop instance is required");
+ return FALSE;
+}
+
+dbus_bool_t
+dbus_py_set_up_server(PyObject *server, PyObject *mainloop)
+{
+ if (NativeMainLoop_Check(mainloop)) {
+ /* Native mainloops are allowed to do arbitrary strange things */
+ NativeMainLoop *nml = (NativeMainLoop *)mainloop;
+ DBusServer *dbs = DBusPyServer_BorrowDBusServer(server);
+
+ if (!dbs) {
+ return FALSE;
+ }
+ return (nml->set_up_server_cb)(dbs, nml->data);
+ }
+ PyErr_SetString(PyExc_TypeError,
+ "A dbus.mainloop.NativeMainLoop instance is required");
+ return FALSE;
+}
+
+/* C API ============================================================ */
+
+PyObject *
+DBusPyNativeMainLoop_New4(dbus_bool_t (*conn_cb)(DBusConnection *, void *),
+ dbus_bool_t (*server_cb)(DBusServer *, void *),
+ void (*free_cb)(void *),
+ void *data)
+{
+ NativeMainLoop *self = PyObject_New(NativeMainLoop, &NativeMainLoop_Type);
+ if (self) {
+ self->data = data;
+ self->free_cb = free_cb;
+ self->set_up_connection_cb = conn_cb;
+ self->set_up_server_cb = server_cb;
+ }
+ return (PyObject *)self;
+}
+
+/* Null mainloop implementation ===================================== */
+
+static dbus_bool_t
+noop_main_loop_cb(void *conn_or_server UNUSED, void *data UNUSED)
+{
+ return TRUE;
+}
+
+#define noop_conn_cb ((dbus_bool_t (*)(DBusConnection *, void *))(noop_main_loop_cb))
+#define noop_server_cb ((dbus_bool_t (*)(DBusServer *, void *))(noop_main_loop_cb))
+
+/* Initialization =================================================== */
+
+dbus_bool_t
+dbus_py_init_mainloop(void)
+{
+ if (PyType_Ready (&NativeMainLoop_Type) < 0) return 0;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_mainloop_types(PyObject *this_module)
+{
+ PyObject *null_main_loop = DBusPyNativeMainLoop_New4(noop_conn_cb,
+ noop_server_cb,
+ NULL,
+ NULL);
+ if (!null_main_loop) return 0;
+
+ if (PyModule_AddObject (this_module, "NativeMainLoop",
+ (PyObject *)&NativeMainLoop_Type) < 0) return 0;
+ if (PyModule_AddObject (this_module, "NULL_MAIN_LOOP",
+ null_main_loop) < 0) return 0;
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/message-append.c b/_dbus_bindings/message-append.c
new file mode 100644
index 0000000..93b76c7
--- /dev/null
+++ b/_dbus_bindings/message-append.c
@@ -0,0 +1,1092 @@
+/* D-Bus Message serialization. This contains all the logic to map from
+ * Python objects to D-Bus types.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define DBG_IS_TOO_VERBOSE
+#include "types-internal.h"
+#include "message-internal.h"
+
+/* Return the number of variants wrapping the given object. Return 0
+ * if the object is not a D-Bus type.
+ */
+static long
+get_variant_level(PyObject *obj)
+{
+ if (DBusPyIntBase_Check(obj)) {
+ return ((DBusPyIntBase *)obj)->variant_level;
+ }
+ else if (DBusPyFloatBase_Check(obj)) {
+ return ((DBusPyFloatBase *)obj)->variant_level;
+ }
+ else if (DBusPyArray_Check(obj)) {
+ return ((DBusPyArray *)obj)->variant_level;
+ }
+ else if (DBusPyDict_Check(obj)) {
+ return ((DBusPyDict *)obj)->variant_level;
+ }
+ else if (DBusPyString_Check(obj)) {
+ return ((DBusPyString *)obj)->variant_level;
+ }
+ else if (DBusPyLongBase_Check(obj) ||
+ DBusPyStrBase_Check(obj) ||
+ DBusPyStruct_Check(obj)) {
+ return dbus_py_variant_level_get(obj);
+ }
+ else {
+ return 0;
+ }
+}
+
+char dbus_py_Message_append__doc__[] = (
+"set_args(*args[, **kwargs])\n\n"
+"Set the message's arguments from the positional parameter, according to\n"
+"the signature given by the ``signature`` keyword parameter.\n"
+"\n"
+"The following type conversions are supported:\n\n"
+"=============================== ===========================\n"
+"D-Bus (in signature) Python\n"
+"=============================== ===========================\n"
+"boolean (b) any object (via bool())\n"
+"byte (y) string of length 1\n"
+" any integer\n"
+"any integer type any integer\n"
+"double (d) any float\n"
+"object path anything with a __dbus_object_path__ attribute\n"
+"string, signature, object path str (must be UTF-8) or unicode\n"
+"dict (a{...}) any mapping\n"
+"array (a...) any iterable over appropriate objects\n"
+"struct ((...)) any iterable over appropriate objects\n"
+"variant any object above (guess type as below)\n"
+"=============================== ===========================\n"
+"\n"
+"Here 'any integer' means anything on which int() or long()\n"
+"(as appropriate) will work, except for basestring subclasses.\n"
+"'Any float' means anything on which float() will work, except\n"
+"for basestring subclasses.\n"
+"\n"
+"If there is no signature, guess from the arguments using\n"
+"the static method `Message.guess_signature`.\n"
+);
+
+char dbus_py_Message_guess_signature__doc__[] = (
+"guess_signature(*args) -> Signature [static method]\n\n"
+"Guess a D-Bus signature which should be used to encode the given\n"
+"Python objects.\n"
+"\n"
+"The signature is constructed as follows:\n\n"
+"+-------------------------------+---------------------------+\n"
+"|Python |D-Bus |\n"
+"+===============================+===========================+\n"
+"|D-Bus type, variant_level > 0 |variant (v) |\n"
+"+-------------------------------+---------------------------+\n"
+"|D-Bus type, variant_level == 0 |the corresponding type |\n"
+"+-------------------------------+---------------------------+\n"
+"|anything with a |object path |\n"
+"|__dbus_object_path__ attribute | |\n"
+"+-------------------------------+---------------------------+\n"
+"|bool |boolean (y) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other int subclass |int32 (i) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other long subclass |int64 (x) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other float subclass |double (d) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other str subclass |string (s) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other unicode subclass |string (s) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other tuple subclass |struct ((...)) |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other list subclass |array (a...), guess |\n"
+"| |contents' type according to|\n"
+"| |type of first item |\n"
+"+-------------------------------+---------------------------+\n"
+"|any other dict subclass |dict (a{...}), guess key, |\n"
+"| |value type according to |\n"
+"| |types for an arbitrary item|\n"
+"+-------------------------------+---------------------------+\n"
+"|anything else |raise TypeError |\n"
+"+-------------------------------+---------------------------+\n"
+);
+
+/* return a new reference, possibly to None */
+static PyObject *
+get_object_path(PyObject *obj)
+{
+ PyObject *magic_attr = PyObject_GetAttr(obj, dbus_py__dbus_object_path__const);
+
+ if (magic_attr) {
+ if (PyString_Check(magic_attr)) {
+ return magic_attr;
+ }
+ else {
+ Py_DECREF(magic_attr);
+ PyErr_SetString(PyExc_TypeError, "__dbus_object_path__ must be "
+ "a string");
+ return NULL;
+ }
+ }
+ else {
+ /* Ignore exceptions, except for SystemExit and KeyboardInterrupt */
+ if (PyErr_ExceptionMatches(PyExc_SystemExit) ||
+ PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
+ return NULL;
+ PyErr_Clear();
+ Py_RETURN_NONE;
+ }
+}
+
+/* Return a new reference. If the object is a variant and variant_level_ptr
+ * is not NULL, put the variant level in the variable pointed to, and
+ * return the contained type instead of "v". */
+static PyObject *
+_signature_string_from_pyobject(PyObject *obj, long *variant_level_ptr)
+{
+ PyObject *magic_attr;
+ long variant_level = get_variant_level(obj);
+ if (variant_level_ptr) {
+ *variant_level_ptr = variant_level;
+ }
+ else if (variant_level > 0) {
+ return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING);
+ }
+
+ if (obj == Py_True || obj == Py_False) {
+ return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING);
+ }
+
+ magic_attr = get_object_path(obj);
+ if (!magic_attr)
+ return NULL;
+ if (magic_attr != Py_None) {
+ Py_DECREF(magic_attr);
+ return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING);
+ }
+ Py_DECREF(magic_attr);
+
+ /* Ordering is important: some of these are subclasses of each other. */
+ if (PyInt_Check(obj)) {
+ if (DBusPyInt16_Check(obj))
+ return PyString_FromString(DBUS_TYPE_INT16_AS_STRING);
+ else if (DBusPyInt32_Check(obj))
+ return PyString_FromString(DBUS_TYPE_INT32_AS_STRING);
+ else if (DBusPyByte_Check(obj))
+ return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING);
+ else if (DBusPyUInt16_Check(obj))
+ return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING);
+ else if (DBusPyBoolean_Check(obj))
+ return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING);
+ else
+ return PyString_FromString(DBUS_TYPE_INT32_AS_STRING);
+ }
+ else if (PyLong_Check(obj)) {
+ if (DBusPyInt64_Check(obj))
+ return PyString_FromString(DBUS_TYPE_INT64_AS_STRING);
+ else if (DBusPyUInt32_Check(obj))
+ return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING);
+ else if (DBusPyUInt64_Check(obj))
+ return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING);
+ else
+ return PyString_FromString(DBUS_TYPE_INT64_AS_STRING);
+ }
+ else if (PyUnicode_Check(obj))
+ return PyString_FromString(DBUS_TYPE_STRING_AS_STRING);
+ else if (PyFloat_Check(obj)) {
+#ifdef WITH_DBUS_FLOAT32
+ if (DBusPyDouble_Check(obj))
+ return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING);
+ else if (DBusPyFloat_Check(obj))
+ return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING);
+ else
+#endif
+ return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING);
+ }
+ else if (PyString_Check(obj)) {
+ if (DBusPyObjectPath_Check(obj))
+ return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING);
+ else if (DBusPySignature_Check(obj))
+ return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING);
+ else if (DBusPyByteArray_Check(obj))
+ return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_TYPE_BYTE_AS_STRING);
+ else
+ return PyString_FromString(DBUS_TYPE_STRING_AS_STRING);
+ }
+ else if (PyTuple_Check(obj)) {
+ Py_ssize_t len = PyTuple_GET_SIZE(obj);
+ PyObject *list = PyList_New(len + 2); /* new ref */
+ PyObject *item; /* temporary new ref */
+ PyObject *empty_str; /* temporary new ref */
+ PyObject *ret;
+ Py_ssize_t i;
+
+ if (!list) return NULL;
+ if (len == 0) {
+ PyErr_SetString(PyExc_ValueError, "D-Bus structs cannot be empty");
+ Py_DECREF(list);
+ return NULL;
+ }
+ /* Set the first and last elements of list to be the parentheses */
+ item = PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
+ if (PyList_SetItem(list, 0, item) < 0) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item = PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING);
+ if (PyList_SetItem(list, len + 1, item) < 0) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ if (!item || !PyList_GET_ITEM(list, 0)) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item = NULL;
+
+ for (i = 0; i < len; i++) {
+ item = PyTuple_GetItem(obj, i);
+ if (!item) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item = _signature_string_from_pyobject(item, NULL);
+ if (!item) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ if (PyList_SetItem(list, i + 1, item) < 0) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item = NULL;
+ }
+ empty_str = PyString_FromString("");
+ if (!empty_str) {
+ /* really shouldn't happen */
+ Py_DECREF(list);
+ return NULL;
+ }
+ ret = PyObject_CallMethod(empty_str, "join", "(O)", list); /* new ref */
+ /* whether ret is NULL or not, */
+ Py_DECREF(empty_str);
+ Py_DECREF(list);
+ return ret;
+ }
+ else if (PyList_Check(obj)) {
+ PyObject *tmp;
+ PyObject *ret = PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING);
+ if (!ret) return NULL;
+ if (DBusPyArray_Check(obj) && PyString_Check(((DBusPyArray *)obj)->signature)) {
+ PyString_Concat(&ret, ((DBusPyArray *)obj)->signature);
+ return ret;
+ }
+ if (PyList_GET_SIZE(obj) == 0) {
+ /* No items, so fail. Or should we guess "av"? */
+ PyErr_SetString(PyExc_ValueError, "Unable to guess signature "
+ "from an empty list");
+ return NULL;
+ }
+ tmp = PyList_GetItem(obj, 0);
+ tmp = _signature_string_from_pyobject(tmp, NULL);
+ if (!tmp) return NULL;
+ PyString_ConcatAndDel(&ret, tmp);
+ return ret;
+ }
+ else if (PyDict_Check(obj)) {
+ PyObject *key, *value, *keysig, *valuesig;
+ Py_ssize_t pos = 0;
+ PyObject *ret = NULL;
+
+ if (DBusPyDict_Check(obj) && PyString_Check(((DBusPyDict *)obj)->signature)) {
+ const char *sig = PyString_AS_STRING(((DBusPyDict *)obj)->signature);
+
+ return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ "%s"
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
+ sig);
+ }
+ if (!PyDict_Next(obj, &pos, &key, &value)) {
+ /* No items, so fail. Or should we guess "a{vv}"? */
+ PyErr_SetString(PyExc_ValueError, "Unable to guess signature "
+ "from an empty dict");
+ return NULL;
+ }
+ keysig = _signature_string_from_pyobject(key, NULL);
+ valuesig = _signature_string_from_pyobject(value, NULL);
+ if (keysig && valuesig) {
+ ret = PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ "%s%s"
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
+ PyString_AS_STRING(keysig),
+ PyString_AS_STRING(valuesig));
+ }
+ Py_XDECREF(keysig);
+ Py_XDECREF(valuesig);
+ return ret;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError, "Don't know how which D-Bus type "
+ "to use to encode type \"%s\"",
+ obj->ob_type->tp_name);
+ return NULL;
+ }
+}
+
+PyObject *
+dbus_py_Message_guess_signature(PyObject *unused UNUSED, PyObject *args)
+{
+ PyObject *tmp, *ret = NULL;
+
+ if (!args) {
+ if (!PyErr_Occurred()) {
+ PyErr_BadInternalCall();
+ }
+ return NULL;
+ }
+
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: called Message_guess_signature", (long)getpid());
+ PyObject_Print(args, stderr, 0);
+ fprintf(stderr, "\n");
+#endif
+
+ if (!PyTuple_Check(args)) {
+ DBG("%s", "Message_guess_signature: args not a tuple");
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+ /* if there were no args, easy */
+ if (PyTuple_GET_SIZE(args) == 0) {
+ DBG("%s", "Message_guess_signature: no args, so return Signature('')");
+ return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", "");
+ }
+
+ /* if there were args, the signature we want is, by construction,
+ * exactly the signature we get for the tuple args, except that we don't
+ * want the parentheses. */
+ tmp = _signature_string_from_pyobject(args, NULL);
+ if (!tmp) {
+ DBG("%s", "Message_guess_signature: failed");
+ return NULL;
+ }
+ if (!PyString_Check(tmp) || PyString_GET_SIZE(tmp) < 2) {
+ PyErr_SetString(PyExc_RuntimeError, "Internal error: "
+ "_signature_string_from_pyobject returned "
+ "a bad result");
+ Py_DECREF(tmp);
+ return NULL;
+ }
+ ret = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s#)",
+ PyString_AS_STRING(tmp) + 1,
+ PyString_GET_SIZE(tmp) - 2);
+ DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret,
+ ret ? PyString_AS_STRING(ret) : "(NULL)");
+ Py_DECREF(tmp);
+ return ret;
+}
+
+static int _message_iter_append_pyobject(DBusMessageIter *appender,
+ DBusSignatureIter *sig_iter,
+ PyObject *obj,
+ dbus_bool_t *more);
+static int _message_iter_append_variant(DBusMessageIter *appender,
+ PyObject *obj);
+
+static int
+_message_iter_append_string(DBusMessageIter *appender,
+ int sig_type, PyObject *obj,
+ dbus_bool_t allow_object_path_attr)
+{
+ char *s;
+
+ if (sig_type == DBUS_TYPE_OBJECT_PATH && allow_object_path_attr) {
+ PyObject *object_path = get_object_path (obj);
+
+ if (object_path == Py_None) {
+ Py_DECREF(object_path);
+ }
+ else if (!object_path) {
+ return -1;
+ }
+ else {
+ int ret = _message_iter_append_string(appender, sig_type,
+ object_path, FALSE);
+ Py_DECREF(object_path);
+ return ret;
+ }
+ }
+
+ if (PyString_Check(obj)) {
+ PyObject *unicode;
+
+ /* Raise TypeError if the string has embedded NULs */
+ if (PyString_AsStringAndSize(obj, &s, NULL) < 0) return -1;
+ /* Surely there's a faster stdlib way to validate UTF-8... */
+ unicode = PyUnicode_DecodeUTF8(s, PyString_GET_SIZE(obj), NULL);
+ if (!unicode) {
+ PyErr_SetString(PyExc_UnicodeError, "String parameters "
+ "to be sent over D-Bus must be valid UTF-8");
+ return -1;
+ }
+ Py_DECREF(unicode);
+ unicode = NULL;
+
+ DBG("Performing actual append: string %s", s);
+ if (!dbus_message_iter_append_basic(appender, sig_type,
+ &s)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ }
+ else if (PyUnicode_Check(obj)) {
+ PyObject *utf8 = PyUnicode_AsUTF8String(obj);
+ if (!utf8) return -1;
+ /* Raise TypeError if the string has embedded NULs */
+ if (PyString_AsStringAndSize(utf8, &s, NULL) < 0) return -1;
+ DBG("Performing actual append: string (from unicode) %s", s);
+ if (!dbus_message_iter_append_basic(appender, sig_type, &s)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ Py_DECREF(utf8);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "Expected a string or unicode object");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_message_iter_append_byte(DBusMessageIter *appender, PyObject *obj)
+{
+ unsigned char y;
+
+ if (PyString_Check(obj)) {
+ if (PyString_GET_SIZE(obj) != 1) {
+ PyErr_Format(PyExc_ValueError, "Expected a string of "
+ "length 1 byte, but found %d bytes",
+ PyString_GET_SIZE(obj));
+ return -1;
+ }
+ y = *(unsigned char *)PyString_AS_STRING(obj);
+ }
+ else {
+ long i = PyInt_AsLong(obj);
+
+ if (i == -1 && PyErr_Occurred()) return -1;
+ if (i < 0 || i > 0xff) {
+ PyErr_Format(PyExc_ValueError, "%d outside range for a "
+ "byte value", (int)i);
+ return -1;
+ }
+ y = i;
+ }
+ DBG("Performing actual append: byte \\x%02x", (unsigned)y);
+ if (!dbus_message_iter_append_basic(appender, DBUS_TYPE_BYTE, &y)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_message_iter_append_dictentry(DBusMessageIter *appender,
+ DBusSignatureIter *sig_iter,
+ PyObject *dict, PyObject *key)
+{
+ DBusSignatureIter sub_sig_iter;
+ DBusMessageIter sub;
+ int ret = -1;
+ PyObject *value = PyObject_GetItem(dict, key);
+ dbus_bool_t more;
+
+ if (!value) return -1;
+
+#ifdef USING_DBG
+ fprintf(stderr, "Append dictentry: ");
+ PyObject_Print(key, stderr, 0);
+ fprintf(stderr, " => ");
+ PyObject_Print(value, stderr, 0);
+ fprintf(stderr, "\n");
+#endif
+
+ DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
+ dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
+#ifdef USING_DBG
+ {
+ char *s;
+ s = dbus_signature_iter_get_signature(sig_iter);
+ DBG("Signature of parent iterator %p is %s", sig_iter, s);
+ dbus_free(s);
+ s = dbus_signature_iter_get_signature(&sub_sig_iter);
+ DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
+ dbus_free(s);
+ }
+#endif
+
+ DBG("%s", "Opening DICT_ENTRY container");
+ if (!dbus_message_iter_open_container(appender, DBUS_TYPE_DICT_ENTRY,
+ NULL, &sub)) {
+ PyErr_NoMemory();
+ goto out;
+ }
+ ret = _message_iter_append_pyobject(&sub, &sub_sig_iter, key, &more);
+ if (ret == 0) {
+ ret = _message_iter_append_pyobject(&sub, &sub_sig_iter, value, &more);
+ }
+ DBG("%s", "Closing DICT_ENTRY container");
+ if (!dbus_message_iter_close_container(appender, &sub)) {
+ PyErr_NoMemory();
+ ret = -1;
+ }
+out:
+ Py_DECREF(value);
+ return ret;
+}
+
+static int
+_message_iter_append_multi(DBusMessageIter *appender,
+ const DBusSignatureIter *sig_iter,
+ int mode, PyObject *obj)
+{
+ DBusMessageIter sub_appender;
+ DBusSignatureIter sub_sig_iter;
+ PyObject *contents;
+ int ret;
+ PyObject *iterator = PyObject_GetIter(obj);
+ char *sig = NULL;
+ int container = mode;
+ dbus_bool_t is_byte_array = DBusPyByteArray_Check(obj);
+ int inner_type;
+ dbus_bool_t more;
+
+#ifdef USING_DBG
+ fprintf(stderr, "Appending multiple: ");
+ PyObject_Print(obj, stderr, 0);
+ fprintf(stderr, "\n");
+#endif
+
+ if (!iterator) return -1;
+ if (mode == DBUS_TYPE_DICT_ENTRY) container = DBUS_TYPE_ARRAY;
+
+ DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
+ dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
+#ifdef USING_DBG
+ {
+ char *s;
+ s = dbus_signature_iter_get_signature(sig_iter);
+ DBG("Signature of parent iterator %p is %s", sig_iter, s);
+ dbus_free(s);
+ s = dbus_signature_iter_get_signature(&sub_sig_iter);
+ DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
+ dbus_free(s);
+ }
+#endif
+ inner_type = dbus_signature_iter_get_current_type(&sub_sig_iter);
+
+ if (mode == DBUS_TYPE_ARRAY || mode == DBUS_TYPE_DICT_ENTRY) {
+ sig = dbus_signature_iter_get_signature(&sub_sig_iter);
+ if (!sig) {
+ PyErr_NoMemory();
+ ret = -1;
+ goto out;
+ }
+ }
+ /* else leave sig set to NULL. */
+
+ DBG("Opening %c container", container);
+ if (!dbus_message_iter_open_container(appender, container,
+ sig, &sub_appender)) {
+ PyErr_NoMemory();
+ ret = -1;
+ goto out;
+ }
+ ret = 0;
+ while ((contents = PyIter_Next(iterator))) {
+
+ if (mode == DBUS_TYPE_ARRAY || mode == DBUS_TYPE_DICT_ENTRY) {
+ DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
+ dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
+#ifdef USING_DBG
+ {
+ char *s;
+ s = dbus_signature_iter_get_signature(sig_iter);
+ DBG("Signature of parent iterator %p is %s", sig_iter, s);
+ dbus_free(s);
+ s = dbus_signature_iter_get_signature(&sub_sig_iter);
+ DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
+ dbus_free(s);
+ }
+#endif
+ }
+
+ if (mode == DBUS_TYPE_DICT_ENTRY) {
+ ret = _message_iter_append_dictentry(&sub_appender, &sub_sig_iter,
+ obj, contents);
+ }
+ else if (mode == DBUS_TYPE_ARRAY && is_byte_array
+ && inner_type == DBUS_TYPE_VARIANT) {
+ /* Subscripting a ByteArray gives a str of length 1, but if the
+ * container is a ByteArray and the parameter is an array of
+ * variants, we want to produce an array of variants containing
+ * bytes, not strings.
+ */
+ PyObject *args = Py_BuildValue("(O)", contents);
+ PyObject *byte;
+
+ if (!args)
+ break;
+ byte = PyObject_Call((PyObject *)&DBusPyByte_Type, args, NULL);
+ Py_DECREF(args);
+ if (!byte)
+ break;
+ ret = _message_iter_append_variant(&sub_appender, byte);
+ Py_DECREF(byte);
+ }
+ else {
+ /* advances sub_sig_iter and sets more on success - for array
+ * this doesn't matter, for struct it's essential */
+ ret = _message_iter_append_pyobject(&sub_appender, &sub_sig_iter,
+ contents, &more);
+ }
+
+ Py_DECREF(contents);
+ if (ret < 0) {
+ break;
+ }
+ }
+
+ if (PyErr_Occurred()) {
+ ret = -1;
+ }
+ else if (mode == DBUS_TYPE_STRUCT && more) {
+ PyErr_Format(PyExc_TypeError, "More items found in struct's D-Bus "
+ "signature than in Python arguments ");
+ ret = -1;
+ }
+
+ /* This must be run as cleanup, even on failure. */
+ DBG("Closing %c container", container);
+ if (!dbus_message_iter_close_container(appender, &sub_appender)) {
+ PyErr_NoMemory();
+ ret = -1;
+ }
+
+out:
+ Py_XDECREF(iterator);
+ dbus_free(sig);
+ return ret;
+}
+
+static int
+_message_iter_append_string_as_byte_array(DBusMessageIter *appender,
+ PyObject *obj)
+{
+ /* a bit of a faster path for byte arrays that are strings */
+ Py_ssize_t len = PyString_GET_SIZE(obj);
+ const char *s;
+ DBusMessageIter sub;
+ int ret;
+
+ s = PyString_AS_STRING(obj);
+ DBG("%s", "Opening ARRAY container");
+ if (!dbus_message_iter_open_container(appender, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING, &sub)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ DBG("Appending fixed array of %d bytes", len);
+ if (dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &s, len)) {
+ ret = 0;
+ }
+ else {
+ PyErr_NoMemory();
+ ret = -1;
+ }
+ DBG("%s", "Closing ARRAY container");
+ if (!dbus_message_iter_close_container(appender, &sub)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return ret;
+}
+
+/* Encode some Python object into a D-Bus variant slot. */
+static int
+_message_iter_append_variant(DBusMessageIter *appender, PyObject *obj)
+{
+ DBusSignatureIter obj_sig_iter;
+ const char *obj_sig_str;
+ PyObject *obj_sig;
+ int ret;
+ long variant_level;
+ dbus_bool_t dummy;
+
+ /* Separate the object into the contained object, and the number of
+ * variants it's wrapped in. */
+ obj_sig = _signature_string_from_pyobject(obj, &variant_level);
+ if (!obj_sig) return -1;
+
+ obj_sig_str = PyString_AsString(obj_sig);
+ if (!obj_sig_str) return -1;
+
+ if (variant_level < 1) {
+ variant_level = 1;
+ }
+
+ dbus_signature_iter_init(&obj_sig_iter, obj_sig_str);
+
+ { /* scope for variant_iters */
+ DBusMessageIter variant_iters[variant_level];
+ long i;
+
+ for (i = 0; i < variant_level; i++) {
+ DBusMessageIter *child = &variant_iters[i];
+ /* The first is a special case: its parent is the iter passed in
+ * to this function, instead of being the previous one in the
+ * stack
+ */
+ DBusMessageIter *parent = (i == 0
+ ? appender
+ : &(variant_iters[i-1]));
+ /* The last is also a special case: it contains the actual
+ * object, rather than another variant
+ */
+ const char *sig_str = (i == variant_level-1
+ ? obj_sig_str
+ : DBUS_TYPE_VARIANT_AS_STRING);
+
+ DBG("Opening VARIANT container %p inside %p containing '%s'",
+ child, parent, sig_str);
+ if (!dbus_message_iter_open_container(parent, DBUS_TYPE_VARIANT,
+ sig_str, child)) {
+ PyErr_NoMemory();
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* Put the object itself into the innermost variant */
+ ret = _message_iter_append_pyobject(&variant_iters[variant_level-1],
+ &obj_sig_iter, obj, &dummy);
+
+ /* here we rely on i (and variant_level) being a signed long */
+ for (i = variant_level - 1; i >= 0; i--) {
+ DBusMessageIter *child = &variant_iters[i];
+ /* The first is a special case: its parent is the iter passed in
+ * to this function, instead of being the previous one in the
+ * stack
+ */
+ DBusMessageIter *parent = (i == 0 ? appender
+ : &(variant_iters[i-1]));
+
+ DBG("Closing VARIANT container %p inside %p", child, parent);
+ if (!dbus_message_iter_close_container(parent, child)) {
+ PyErr_NoMemory();
+ ret = -1;
+ goto out;
+ }
+ }
+
+ }
+
+out:
+ Py_XDECREF(obj_sig);
+ return ret;
+}
+
+/* On success, *more is set to whether there's more in the signature. */
+static int
+_message_iter_append_pyobject(DBusMessageIter *appender,
+ DBusSignatureIter *sig_iter,
+ PyObject *obj,
+ dbus_bool_t *more)
+{
+ int sig_type = dbus_signature_iter_get_current_type(sig_iter);
+ union {
+ dbus_bool_t b;
+ double d;
+ dbus_uint16_t uint16;
+ dbus_int16_t int16;
+ dbus_uint32_t uint32;
+ dbus_int32_t int32;
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+ dbus_uint64_t uint64;
+ dbus_int64_t int64;
+#endif
+ } u;
+ int ret = -1;
+
+#ifdef USING_DBG
+ fprintf(stderr, "Appending object at %p: ", obj);
+ PyObject_Print(obj, stderr, 0);
+ fprintf(stderr, " into appender at %p, dbus wants type %c\n",
+ appender, sig_type);
+#endif
+
+ switch (sig_type) {
+ /* The numeric types are relatively simple to deal with, so are
+ * inlined here. */
+
+ case DBUS_TYPE_BOOLEAN:
+ if (PyObject_IsTrue(obj)) {
+ u.b = 1;
+ }
+ else {
+ u.b = 0;
+ }
+ DBG("Performing actual append: bool(%ld)", (long)u.b);
+ if (!dbus_message_iter_append_basic(appender, sig_type, &u.b)) {
+ PyErr_NoMemory();
+ ret = -1;
+ break;
+ }
+ ret = 0;
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ u.d = PyFloat_AsDouble(obj);
+ if (PyErr_Occurred()) {
+ ret = -1;
+ break;
+ }
+ DBG("Performing actual append: double(%f)", u.d);
+ if (!dbus_message_iter_append_basic(appender, sig_type, &u.d)) {
+ PyErr_NoMemory();
+ ret = -1;
+ break;
+ }
+ ret = 0;
+ break;
+
+#ifdef WITH_DBUS_FLOAT32
+ case DBUS_TYPE_FLOAT:
+ u.d = PyFloat_AsDouble(obj);
+ if (PyErr_Occurred()) {
+ ret = -1;
+ break;
+ }
+ u.f = (float)u.d;
+ DBG("Performing actual append: float(%f)", u.f);
+ if (!dbus_message_iter_append_basic(appender, sig_type, &u.f)) {
+ PyErr_NoMemory();
+ ret = -1;
+ break;
+ }
+ ret = 0;
+ break;
+#endif
+
+ /* The integer types are all basically the same - we delegate to
+ intNN_range_check() */
+#define PROCESS_INTEGER(size) \
+ u.size = dbus_py_##size##_range_check(obj);\
+ if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
+ ret = -1; \
+ break; \
+ }\
+ DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
+ if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
+ PyErr_NoMemory();\
+ ret = -1;\
+ break;\
+ } \
+ ret = 0;
+
+ case DBUS_TYPE_INT16:
+ PROCESS_INTEGER(int16)
+ break;
+ case DBUS_TYPE_UINT16:
+ PROCESS_INTEGER(uint16)
+ break;
+ case DBUS_TYPE_INT32:
+ PROCESS_INTEGER(int32)
+ break;
+ case DBUS_TYPE_UINT32:
+ PROCESS_INTEGER(uint32)
+ break;
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+ case DBUS_TYPE_INT64:
+ PROCESS_INTEGER(int64)
+ break;
+ case DBUS_TYPE_UINT64:
+ PROCESS_INTEGER(uint64)
+ break;
+#else
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ PyErr_SetString(PyExc_NotImplementedError, "64-bit integer "
+ "types are not supported on this platform");
+ ret = -1;
+ break;
+#endif
+#undef PROCESS_INTEGER
+
+ /* Now the more complicated cases, which are delegated to helper
+ * functions (although in practice, the compiler will hopefully
+ * inline them anyway). */
+
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_OBJECT_PATH:
+ ret = _message_iter_append_string(appender, sig_type, obj, TRUE);
+ break;
+
+ case DBUS_TYPE_BYTE:
+ ret = _message_iter_append_byte(appender, obj);
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ /* 3 cases - it might actually be a dict, or it might be a byte array
+ * being copied from a string (for which we have a faster path),
+ * or it might be a generic array. */
+
+ sig_type = dbus_signature_iter_get_element_type(sig_iter);
+ if (sig_type == DBUS_TYPE_DICT_ENTRY)
+ ret = _message_iter_append_multi(appender, sig_iter,
+ DBUS_TYPE_DICT_ENTRY, obj);
+ else if (sig_type == DBUS_TYPE_BYTE && PyString_Check(obj))
+ ret = _message_iter_append_string_as_byte_array(appender, obj);
+ else
+ ret = _message_iter_append_multi(appender, sig_iter,
+ DBUS_TYPE_ARRAY, obj);
+ DBG("_message_iter_append_multi(): %d", ret);
+ break;
+
+ case DBUS_TYPE_STRUCT:
+ ret = _message_iter_append_multi(appender, sig_iter, sig_type, obj);
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ ret = _message_iter_append_variant(appender, obj);
+ break;
+
+ case DBUS_TYPE_INVALID:
+ PyErr_SetString(PyExc_TypeError, "Fewer items found in D-Bus "
+ "signature than in Python arguments");
+ ret = -1;
+ break;
+
+ default:
+ PyErr_Format(PyExc_TypeError, "Unknown type '\\x%x' in D-Bus "
+ "signature", sig_type);
+ ret = -1;
+ break;
+ }
+ if (ret < 0) return -1;
+
+ DBG("Advancing signature iter at %p", sig_iter);
+ *more = dbus_signature_iter_next(sig_iter);
+#ifdef USING_DBG
+ DBG("- result: %ld, type %02x '%c'", (long)(*more),
+ (int)dbus_signature_iter_get_current_type(sig_iter),
+ (int)dbus_signature_iter_get_current_type(sig_iter));
+#endif
+ return 0;
+}
+
+
+PyObject *
+dbus_py_Message_append(Message *self, PyObject *args, PyObject *kwargs)
+{
+ const char *signature = NULL;
+ PyObject *signature_obj = NULL;
+ DBusSignatureIter sig_iter;
+ DBusMessageIter appender;
+ int i;
+ static char *argnames[] = {"signature", NULL};
+ /* must start FALSE for the case where there's nothing there and we
+ * never iterate at all */
+ dbus_bool_t more;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: called Message_append(*", (long)getpid());
+ PyObject_Print(args, stderr, 0);
+ if (kwargs) {
+ fprintf(stderr, ", **");
+ PyObject_Print(kwargs, stderr, 0);
+ }
+ fprintf(stderr, ")\n");
+#endif
+
+ /* only use kwargs for this step: deliberately ignore args for now */
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|z:append",
+ argnames, &signature)) return NULL;
+
+ if (!signature) {
+ DBG("%s", "No signature for message, guessing...");
+ signature_obj = dbus_py_Message_guess_signature(NULL, args);
+ if (!signature_obj) return NULL;
+ signature = PyString_AS_STRING(signature_obj);
+ }
+ /* from here onwards, you have to do a goto rather than returning NULL
+ to make sure signature_obj gets freed */
+
+ /* iterate over args and the signature, together */
+ if (!dbus_signature_validate(signature, NULL)) {
+ PyErr_SetString(PyExc_ValueError, "Corrupt type signature");
+ goto err;
+ }
+ dbus_signature_iter_init(&sig_iter, signature);
+ dbus_message_iter_init_append(self->msg, &appender);
+ more = (signature[0] != '\0');
+ for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+ if (_message_iter_append_pyobject(&appender, &sig_iter,
+ PyTuple_GET_ITEM(args, i),
+ &more) < 0) {
+ goto hosed;
+ }
+ }
+ if (more) {
+ PyErr_SetString(PyExc_TypeError, "More items found in D-Bus "
+ "signature than in Python arguments");
+ goto hosed;
+ }
+
+ /* success! */
+ Py_XDECREF(signature_obj);
+ Py_RETURN_NONE;
+
+hosed:
+ /* "If appending any of the arguments fails due to lack of memory,
+ * generally the message is hosed and you have to start over" -libdbus docs
+ * Enforce this by throwing away the message structure.
+ */
+ dbus_message_unref(self->msg);
+ self->msg = NULL;
+err:
+ Py_XDECREF(signature_obj);
+ return NULL;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/message-get-args.c b/_dbus_bindings/message-get-args.c
new file mode 100644
index 0000000..7d55ffd
--- /dev/null
+++ b/_dbus_bindings/message-get-args.c
@@ -0,0 +1,523 @@
+/* D-Bus Message unserialization. This contains all the logic to map from
+ * D-Bus types to Python objects.
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define PY_SIZE_T_CLEAN 1
+
+#define DBG_IS_TOO_VERBOSE
+#include "types-internal.h"
+#include "message-internal.h"
+
+char dbus_py_Message_get_args_list__doc__[] = (
+"get_args_list(**kwargs) -> list\n\n"
+"Return the message's arguments. Keyword arguments control the translation\n"
+"of D-Bus types to Python:\n"
+"\n"
+":Keywords:\n"
+" `byte_arrays` : bool\n"
+" If true, convert arrays of byte (signature 'ay') into dbus.ByteArray,\n"
+" a str subclass. In practice, this is usually what you want, but\n"
+" it's off by default for consistency.\n"
+"\n"
+" If false (default), convert them into a dbus.Array of Bytes.\n"
+" `utf8_strings` : bool\n"
+" If true, return D-Bus strings as Python 8-bit strings (of UTF-8).\n"
+" If false (default), return D-Bus strings as Python unicode objects.\n"
+"\n"
+"Most of the type mappings should be fairly obvious:\n"
+"\n"
+"=============== ===================================================\n"
+"D-Bus Python\n"
+"=============== ===================================================\n"
+"byte (y) dbus.Byte (int subclass)\n"
+"bool (b) dbus.Boolean (int subclass)\n"
+"Signature (g) dbus.Signature (str subclass)\n"
+"intNN, uintNN dbus.IntNN, dbus.UIntNN (int or long subclasses)\n"
+"double (d) dbus.Double\n"
+"string (s) dbus.String (unicode subclass)\n"
+" (or dbus.UTF8String, str subclass, if utf8_strings set)\n"
+"Object path (o) dbus.ObjectPath (str subclass)\n"
+"dict (a{...}) dbus.Dictionary\n"
+"array (a...) dbus.Array (list subclass) containing appropriate types\n"
+"byte array (ay) dbus.ByteArray (str subclass) if byte_arrays set; or\n"
+" list of Byte\n"
+"struct ((...)) dbus.Struct (tuple subclass) of appropriate types\n"
+"variant (v) contained type, but with variant_level > 0\n"
+"=============== ===================================================\n"
+);
+
+typedef struct {
+ int byte_arrays;
+ int utf8_strings;
+} Message_get_args_options;
+
+static PyObject *_message_iter_get_pyobject(DBusMessageIter *iter,
+ Message_get_args_options *opts,
+ long extra_variants);
+
+/* Append all the items iterated over to the given Python list object.
+ * Return 0 on success/-1 with exception on failure. */
+static int
+_message_iter_append_all_to_list(DBusMessageIter *iter, PyObject *list,
+ Message_get_args_options *opts)
+{
+ int ret, type;
+ while ((type = dbus_message_iter_get_arg_type(iter))
+ != DBUS_TYPE_INVALID) {
+ PyObject *item;
+ DBG("type == %d '%c'", type, type);
+
+ item = _message_iter_get_pyobject(iter, opts, 0);
+ if (!item) return -1;
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: appending to list: %p == ", (long)getpid(), item);
+ PyObject_Print(item, stderr, 0);
+ fprintf(stderr, " of type %p\n", item->ob_type);
+#endif
+ ret = PyList_Append(list, item);
+ Py_DECREF(item);
+ item = NULL;
+ if (ret < 0) return -1;
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: list now contains: ", (long)getpid());
+ PyObject_Print(list, stderr, 0);
+ fprintf(stderr, "\n");
+#endif
+ dbus_message_iter_next(iter);
+ }
+ return 0;
+}
+
+static inline PyObject *
+_message_iter_get_dict(DBusMessageIter *iter,
+ Message_get_args_options *opts,
+ PyObject *kwargs)
+{
+ DBusMessageIter entries;
+ char *sig_str = dbus_message_iter_get_signature(iter);
+ PyObject *sig;
+ PyObject *ret;
+ int status;
+
+ if (!sig_str) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ sig = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
+ "(s#)", sig_str+2,
+ (Py_ssize_t)strlen(sig_str)-3);
+ dbus_free(sig_str);
+ if (!sig) {
+ return NULL;
+ }
+ status = PyDict_SetItem(kwargs, dbus_py_signature_const, sig);
+ Py_DECREF(sig);
+ if (status < 0) {
+ return NULL;
+ }
+
+ ret = PyObject_Call((PyObject *)&DBusPyDict_Type, dbus_py_empty_tuple, kwargs);
+ if (!ret) {
+ return NULL;
+ }
+
+ dbus_message_iter_recurse(iter, &entries);
+ while (dbus_message_iter_get_arg_type(&entries) == DBUS_TYPE_DICT_ENTRY) {
+ PyObject *key = NULL;
+ PyObject *value = NULL;
+ DBusMessageIter kv;
+
+ DBG("%s", "dict entry...");
+
+ dbus_message_iter_recurse(&entries, &kv);
+
+ key = _message_iter_get_pyobject(&kv, opts, 0);
+ if (!key) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ dbus_message_iter_next(&kv);
+
+ value = _message_iter_get_pyobject(&kv, opts, 0);
+ if (!value) {
+ Py_DECREF(key);
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ status = PyDict_SetItem(ret, key, value);
+ Py_DECREF(key);
+ Py_DECREF(value);
+
+ if (status < 0) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ dbus_message_iter_next(&entries);
+ }
+
+ return ret;
+}
+
+/* Returns a new reference. */
+static PyObject *
+_message_iter_get_pyobject(DBusMessageIter *iter,
+ Message_get_args_options *opts,
+ long variant_level)
+{
+ union {
+ const char *s;
+ unsigned char y;
+ dbus_bool_t b;
+ double d;
+ float f;
+ dbus_uint16_t u16;
+ dbus_int16_t i16;
+ dbus_uint32_t u32;
+ dbus_int32_t i32;
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+ dbus_uint64_t u64;
+ dbus_int64_t i64;
+#endif
+ } u;
+ int type = dbus_message_iter_get_arg_type(iter);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ /* If the variant-level is >0, prepare a dict for the kwargs.
+ * For variant wrappers optimize slightly by skipping this.
+ */
+ if (variant_level > 0 && type != DBUS_TYPE_VARIANT) {
+ PyObject *variant_level_int;
+
+ variant_level_int = PyInt_FromLong(variant_level);
+ if (!variant_level_int) {
+ return NULL;
+ }
+ kwargs = PyDict_New();
+ if (!kwargs) {
+ Py_DECREF(variant_level_int);
+ return NULL;
+ }
+ if (PyDict_SetItem(kwargs, dbus_py_variant_level_const,
+ variant_level_int) < 0) {
+ Py_DECREF(variant_level_int);
+ Py_DECREF(kwargs);
+ return NULL;
+ }
+ Py_DECREF(variant_level_int);
+ }
+ /* From here down you need to break from the switch to exit, so the
+ * dict is freed if necessary
+ */
+
+ switch (type) {
+ case DBUS_TYPE_STRING:
+ DBG("%s", "found a string");
+ dbus_message_iter_get_basic(iter, &u.s);
+ if (opts->utf8_strings) {
+ args = Py_BuildValue("(s)", u.s);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyUTF8String_Type,
+ args, kwargs);
+ }
+ else {
+ args = Py_BuildValue("(N)", PyUnicode_DecodeUTF8(u.s,
+ strlen(u.s),
+ NULL));
+ if (!args) {
+ break;
+ }
+ ret = PyObject_Call((PyObject *)&DBusPyString_Type,
+ args, kwargs);
+ }
+ break;
+
+ case DBUS_TYPE_SIGNATURE:
+ DBG("%s", "found a signature");
+ dbus_message_iter_get_basic(iter, &u.s);
+ args = Py_BuildValue("(s)", u.s);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPySignature_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ DBG("%s", "found an object path");
+ dbus_message_iter_get_basic(iter, &u.s);
+ args = Py_BuildValue("(s)", u.s);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyObjectPath_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ DBG("%s", "found a double");
+ dbus_message_iter_get_basic(iter, &u.d);
+ args = Py_BuildValue("(f)", u.d);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyDouble_Type, args, kwargs);
+ break;
+
+#ifdef WITH_DBUS_FLOAT32
+ case DBUS_TYPE_FLOAT:
+ DBG("%s", "found a float");
+ dbus_message_iter_get_basic(iter, &u.f);
+ args = Py_BuildValue("(f)", (double)u.f);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyFloat_Type, args, kwargs);
+ break;
+#endif
+
+ case DBUS_TYPE_INT16:
+ DBG("%s", "found an int16");
+ dbus_message_iter_get_basic(iter, &u.i16);
+ args = Py_BuildValue("(i)", (int)u.i16);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyInt16_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_UINT16:
+ DBG("%s", "found a uint16");
+ dbus_message_iter_get_basic(iter, &u.u16);
+ args = Py_BuildValue("(i)", (int)u.u16);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyUInt16_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_INT32:
+ DBG("%s", "found an int32");
+ dbus_message_iter_get_basic(iter, &u.i32);
+ args = Py_BuildValue("(l)", (long)u.i32);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyInt32_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_UINT32:
+ DBG("%s", "found a uint32");
+ dbus_message_iter_get_basic(iter, &u.u32);
+ args = Py_BuildValue("(k)", (unsigned long)u.u32);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyUInt32_Type, args, kwargs);
+ break;
+
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+ case DBUS_TYPE_INT64:
+ DBG("%s", "found an int64");
+ dbus_message_iter_get_basic(iter, &u.i64);
+ args = Py_BuildValue("(L)", (PY_LONG_LONG)u.i64);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyInt64_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_UINT64:
+ DBG("%s", "found a uint64");
+ dbus_message_iter_get_basic(iter, &u.u64);
+ args = Py_BuildValue("(K)", (unsigned PY_LONG_LONG)u.u64);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyUInt64_Type, args, kwargs);
+ break;
+#else
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ PyErr_SetString(PyExc_NotImplementedError,
+ "64-bit integer types are not supported on "
+ "this platform");
+ break;
+#endif
+
+ case DBUS_TYPE_BYTE:
+ DBG("%s", "found a byte");
+ dbus_message_iter_get_basic(iter, &u.y);
+ args = Py_BuildValue("(l)", (long)u.y);
+ if (!args)
+ break;
+ ret = PyObject_Call((PyObject *)&DBusPyByte_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_BOOLEAN:
+ DBG("%s", "found a bool");
+ dbus_message_iter_get_basic(iter, &u.b);
+ args = Py_BuildValue("(l)", (long)u.b);
+ if (!args)
+ break;
+ ret = PyObject_Call((PyObject *)&DBusPyBoolean_Type, args, kwargs);
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ DBG("%s", "found an array...");
+ /* Dicts are arrays of DBUS_TYPE_DICT_ENTRY on the wire.
+ Also, we special-case arrays of DBUS_TYPE_BYTE sometimes. */
+ type = dbus_message_iter_get_element_type(iter);
+ if (type == DBUS_TYPE_DICT_ENTRY) {
+ DBG("%s", "no, actually it's a dict...");
+ if (!kwargs) {
+ kwargs = PyDict_New();
+ if (!kwargs) break;
+ }
+ ret = _message_iter_get_dict(iter, opts, kwargs);
+ }
+ else if (opts->byte_arrays && type == DBUS_TYPE_BYTE) {
+ DBusMessageIter sub;
+ int n;
+
+ DBG("%s", "actually, a byte array...");
+ dbus_message_iter_recurse(iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub,
+ (const unsigned char **)&u.s,
+ &n);
+ args = Py_BuildValue("(s#)", u.s, (Py_ssize_t)n);
+ if (!args) break;
+ ret = PyObject_Call((PyObject *)&DBusPyByteArray_Type,
+ args, kwargs);
+ }
+ else {
+ DBusMessageIter sub;
+ char *sig;
+ PyObject *sig_obj;
+ int status;
+
+ DBG("%s", "a normal array...");
+ if (!kwargs) {
+ kwargs = PyDict_New();
+ if (!kwargs) break;
+ }
+ dbus_message_iter_recurse(iter, &sub);
+ sig = dbus_message_iter_get_signature(&sub);
+ if (!sig) break;
+ sig_obj = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
+ "(s)", sig);
+ dbus_free(sig);
+ if (!sig_obj) break;
+ status = PyDict_SetItem(kwargs, dbus_py_signature_const, sig_obj);
+ Py_DECREF(sig_obj);
+ if (status < 0) break;
+ ret = PyObject_Call((PyObject *)&DBusPyArray_Type,
+ dbus_py_empty_tuple, kwargs);
+ if (!ret) break;
+ if (_message_iter_append_all_to_list(&sub, ret, opts) < 0) {
+ Py_DECREF(ret);
+ ret = NULL;
+ }
+ }
+ break;
+
+ case DBUS_TYPE_STRUCT:
+ {
+ DBusMessageIter sub;
+ PyObject *list = PyList_New(0);
+ PyObject *tuple;
+
+ DBG("%s", "found a struct...");
+ if (!list) break;
+ dbus_message_iter_recurse(iter, &sub);
+ if (_message_iter_append_all_to_list(&sub, list, opts) < 0) {
+ Py_DECREF(list);
+ break;
+ }
+ tuple = Py_BuildValue("(O)", list);
+ if (tuple) {
+ ret = PyObject_Call((PyObject *)&DBusPyStruct_Type, tuple, kwargs);
+ }
+ else {
+ ret = NULL;
+ }
+ /* whether successful or not, we take the same action: */
+ Py_DECREF(list);
+ Py_XDECREF(tuple);
+ }
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ {
+ DBusMessageIter sub;
+
+ DBG("%s", "found a variant...");
+ dbus_message_iter_recurse(iter, &sub);
+ ret = _message_iter_get_pyobject(&sub, opts, variant_level+1);
+ }
+ break;
+
+ default:
+ PyErr_Format(PyExc_TypeError, "Unknown type '\\%x' in D-Bus "
+ "message", type);
+ }
+
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
+
+PyObject *
+dbus_py_Message_get_args_list(Message *self, PyObject *args, PyObject *kwargs)
+{
+ Message_get_args_options opts = { 0, 0 };
+ static char *argnames[] = { "byte_arrays", "utf8_strings", NULL };
+ PyObject *list;
+ DBusMessageIter iter;
+
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: called Message_get_args_list(self, *",
+ (long)getpid());
+ PyObject_Print(args, stderr, 0);
+ if (kwargs) {
+ fprintf(stderr, ", **");
+ PyObject_Print(kwargs, stderr, 0);
+ }
+ fprintf(stderr, ")\n");
+#endif
+
+ if (PyTuple_Size(args) != 0) {
+ PyErr_SetString(PyExc_TypeError, "get_args_list takes no positional "
+ "arguments");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:get_args_list",
+ argnames,
+ &(opts.byte_arrays),
+ &(opts.utf8_strings))) return NULL;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+
+ list = PyList_New(0);
+ if (!list) return NULL;
+
+ /* Iterate over args, if any, appending to list */
+ if (dbus_message_iter_init(self->msg, &iter)) {
+ if (_message_iter_append_all_to_list(&iter, list, &opts) < 0) {
+ Py_DECREF(list);
+ DBG_EXC("%s", "Message_get_args: appending all to list failed:");
+ return NULL;
+ }
+ }
+
+#ifdef USING_DBG
+ fprintf(stderr, "DBG/%ld: message has args list ", (long)getpid());
+ PyObject_Print(list, stderr, 0);
+ fprintf(stderr, "\n");
+#endif
+
+ return list;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/message-internal.h b/_dbus_bindings/message-internal.h
new file mode 100644
index 0000000..7532e38
--- /dev/null
+++ b/_dbus_bindings/message-internal.h
@@ -0,0 +1,49 @@
+/* D-Bus message: implementation internals
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+
+#include "dbus_bindings-internal.h"
+
+#ifndef DBUS_BINDINGS_MESSAGE_INTERNAL_H
+#define DBUS_BINDINGS_MESSAGE_INTERNAL_H
+
+typedef struct {
+ PyObject_HEAD
+ DBusMessage *msg;
+} Message;
+
+extern char dbus_py_Message_append__doc__[];
+extern PyObject *dbus_py_Message_append(Message *, PyObject *, PyObject *);
+extern char dbus_py_Message_guess_signature__doc__[];
+extern PyObject *dbus_py_Message_guess_signature(PyObject *, PyObject *);
+extern char dbus_py_Message_get_args_list__doc__[];
+extern PyObject *dbus_py_Message_get_args_list(Message *,
+ PyObject *,
+ PyObject *);
+
+extern PyObject *DBusPy_RaiseUnusableMessage(void);
+
+#endif
diff --git a/_dbus_bindings/message.c b/_dbus_bindings/message.c
new file mode 100644
index 0000000..a2c04c3
--- /dev/null
+++ b/_dbus_bindings/message.c
@@ -0,0 +1,1063 @@
+/* Implementation of D-Bus Message and subclasses (but see message-get-args.h
+ * and message-append.h for unserialization and serialization code).
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+#include "message-internal.h"
+
+static PyTypeObject MessageType, SignalMessageType, ErrorMessageType;
+static PyTypeObject MethodReturnMessageType, MethodCallMessageType;
+
+static inline int Message_Check(PyObject *o)
+{
+ return (o->ob_type == &MessageType)
+ || PyObject_IsInstance(o, (PyObject *)&MessageType);
+}
+
+PyObject *
+DBusPy_RaiseUnusableMessage(void)
+{
+ DBusPyException_SetString("Message object is uninitialized, or has become "
+ "unusable due to error while appending "
+ "arguments");
+ return NULL;
+}
+
+PyDoc_STRVAR(Message_tp_doc,
+"A message to be sent or received over a D-Bus Connection.\n");
+
+static void Message_tp_dealloc(Message *self)
+{
+ if (self->msg) {
+ dbus_message_unref(self->msg);
+ }
+ self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *
+Message_tp_new(PyTypeObject *type,
+ PyObject *args UNUSED,
+ PyObject *kwargs UNUSED)
+{
+ Message *self;
+
+ self = (Message *)type->tp_alloc(type, 0);
+ if (!self) return NULL;
+ self->msg = NULL;
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(MethodCallMessage_tp_doc, "A method-call message.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.lowlevel.MethodCallMessage(destination: str or None, path: str,\n"
+" interface: str or None, method: str)\n"
+"\n"
+"``destination`` is the destination bus name, or None to send the\n"
+"message directly to the peer (usually the bus daemon).\n"
+"\n"
+"``path`` is the object-path of the object whose method is to be called.\n"
+"\n"
+"``interface`` is the interface qualifying the method name, or None to omit\n"
+"the interface from the message header.\n"
+"\n"
+"``method`` is the method name (member name).\n"
+);
+
+static int
+MethodCallMessage_tp_init(Message *self, PyObject *args, PyObject *kwargs)
+{
+ const char *destination, *path, *interface, *method;
+ static char *kwlist[] = {"destination", "path", "interface", "method", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zszs:__init__", kwlist,
+ &destination, &path, &interface,
+ &method)) {
+ return -1;
+ }
+ if (destination && !dbus_py_validate_bus_name(destination, 1, 1)) return -1;
+ if (!dbus_py_validate_object_path(path)) return -1;
+ if (interface && !dbus_py_validate_interface_name(interface)) return -1;
+ if (!dbus_py_validate_member_name(method)) return -1;
+ if (self->msg) {
+ dbus_message_unref(self->msg);
+ self->msg = NULL;
+ }
+ self->msg = dbus_message_new_method_call(destination, path, interface,
+ method);
+ if (!self->msg) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+PyDoc_STRVAR(MethodReturnMessage_tp_doc, "A method-return message.\n\n"
+"Constructor::\n\n"
+" dbus.lowlevel.MethodReturnMessage(method_call: MethodCallMessage)\n");
+
+static int
+MethodReturnMessage_tp_init(Message *self, PyObject *args, PyObject *kwargs)
+{
+ Message *other;
+ static char *kwlist[] = {"method_call", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:__init__", kwlist,
+ &MessageType, &other)) {
+ return -1;
+ }
+ if (self->msg) {
+ dbus_message_unref(self->msg);
+ self->msg = NULL;
+ }
+ self->msg = dbus_message_new_method_return(other->msg);
+ if (!self->msg) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+PyDoc_STRVAR(SignalMessage_tp_doc, "A signal message.\n\n"
+"Constructor::\n\n"
+" dbus.lowlevel.SignalMessage(path: str, interface: str, method: str)\n");
+static int
+SignalMessage_tp_init(Message *self, PyObject *args, PyObject *kwargs)
+{
+ const char *path, *interface, *name;
+ static char *kwlist[] = {"path", "interface", "name", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss:__init__", kwlist,
+ &path, &interface, &name)) {
+ return -1;
+ }
+ if (!dbus_py_validate_object_path(path)) return -1;
+ if (!dbus_py_validate_interface_name(interface)) return -1;
+ if (!dbus_py_validate_member_name(name)) return -1;
+ if (self->msg) {
+ dbus_message_unref(self->msg);
+ self->msg = NULL;
+ }
+ self->msg = dbus_message_new_signal(path, interface, name);
+ if (!self->msg) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+PyDoc_STRVAR(ErrorMessage_tp_doc, "An error message.\n\n"
+"Constructor::\n\n"
+" dbus.lowlevel.ErrorMessage(reply_to: Message, error_name: str,\n"
+" error_message: str or None)\n");
+static int
+ErrorMessage_tp_init(Message *self, PyObject *args, PyObject *kwargs)
+{
+ Message *reply_to;
+ const char *error_name, *error_message;
+ static char *kwlist[] = {"reply_to", "error_name", "error_message", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!sz:__init__", kwlist,
+ &MessageType, &reply_to, &error_name,
+ &error_message)) {
+ return -1;
+ }
+ if (!dbus_py_validate_error_name(error_name)) return -1;
+ if (self->msg) {
+ dbus_message_unref(self->msg);
+ self->msg = NULL;
+ }
+ self->msg = dbus_message_new_error(reply_to->msg, error_name, error_message);
+ if (!self->msg) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+DBusMessage *
+DBusPyMessage_BorrowDBusMessage(PyObject *msg)
+{
+ if (!Message_Check(msg)) {
+ PyErr_SetString(PyExc_TypeError,
+ "A dbus.lowlevel.Message instance is required");
+ return NULL;
+ }
+ if (!((Message *)msg)->msg) {
+ DBusPy_RaiseUnusableMessage();
+ return NULL;
+ }
+ return ((Message *)msg)->msg;
+}
+
+PyObject *
+DBusPyMessage_ConsumeDBusMessage(DBusMessage *msg)
+{
+ PyTypeObject *type;
+ Message *self;
+
+ switch (dbus_message_get_type(msg)) {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ type = &MethodCallMessageType;
+ break;
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ type = &MethodReturnMessageType;
+ break;
+ case DBUS_MESSAGE_TYPE_ERROR:
+ type = &ErrorMessageType;
+ break;
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ type = &SignalMessageType;
+ break;
+ default:
+ type = &MessageType;
+ }
+
+ self = (Message *)(type->tp_new) (type, dbus_py_empty_tuple, NULL);
+ if (!self) {
+ dbus_message_unref(msg);
+ return NULL;
+ }
+ self->msg = msg;
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(Message_copy__doc__,
+"message.copy() -> Message (or subclass)\n"
+"Deep-copy the message, resetting the serial number to zero.\n");
+static PyObject *
+Message_copy(Message *self, PyObject *args UNUSED)
+{
+ DBusMessage *msg;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ msg = dbus_message_copy(self->msg);
+ if (!msg) return PyErr_NoMemory();
+ return DBusPyMessage_ConsumeDBusMessage(msg);
+}
+
+PyDoc_STRVAR(Message_get_auto_start__doc__,
+"message.get_auto_start() -> bool\n"
+"Return true if this message will cause an owner for the destination name\n"
+"to be auto-started.\n");
+static PyObject *
+Message_get_auto_start(Message *self, PyObject *unused UNUSED)
+{
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_get_auto_start(self->msg));
+}
+
+PyDoc_STRVAR(Message_set_auto_start__doc__,
+"message.set_auto_start(bool) -> None\n"
+"Set whether this message will cause an owner for the destination name\n"
+"to be auto-started.\n");
+static PyObject *
+Message_set_auto_start(Message *self, PyObject *args)
+{
+ int value;
+ if (!PyArg_ParseTuple(args, "i", &value)) return NULL;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ dbus_message_set_auto_start(self->msg, value ? TRUE : FALSE);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(Message_get_no_reply__doc__,
+"message.get_no_reply() -> bool\n"
+"Return true if this message need not be replied to.\n");
+static PyObject *
+Message_get_no_reply(Message *self, PyObject *unused UNUSED)
+{
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_get_no_reply(self->msg));
+}
+
+PyDoc_STRVAR(Message_set_no_reply__doc__,
+"message.set_no_reply(bool) -> None\n"
+"Set whether no reply to this message is required.\n");
+static PyObject *
+Message_set_no_reply(Message *self, PyObject *args)
+{
+ int value;
+ if (!PyArg_ParseTuple(args, "i", &value)) return NULL;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ dbus_message_set_no_reply(self->msg, value ? TRUE : FALSE);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_reply_serial__doc__,
+"message.get_reply_serial() -> long\n"
+"Returns the serial that the message is a reply to or 0 if none.\n");
+static PyObject *
+Message_get_reply_serial(Message *self, PyObject *unused UNUSED)
+{
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyLong_FromUnsignedLong(dbus_message_get_reply_serial(self->msg));
+}
+
+PyDoc_STRVAR(Message_set_reply_serial__doc__,
+"message.set_reply_serial(bool) -> None\n"
+"Set the serial that this message is a reply to.\n");
+static PyObject *
+Message_set_reply_serial(Message *self, PyObject *args)
+{
+ dbus_uint32_t value;
+
+ if (!PyArg_ParseTuple(args, "k", &value)) return NULL;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_message_set_reply_serial(self->msg, value)) {
+ return PyErr_NoMemory();
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(Message_get_type__doc__,
+"message.get_type() -> int\n\n"
+"Returns the type of the message.\n");
+static PyObject *
+Message_get_type(Message *self, PyObject *unused UNUSED)
+{
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyInt_FromLong(dbus_message_get_type(self->msg));
+}
+
+PyDoc_STRVAR(Message_get_serial__doc__,
+"message.get_serial() -> long\n"
+"Returns the serial of a message or 0 if none has been specified.\n"
+"\n"
+"The message's serial number is provided by the application sending the\n"
+"message and is used to identify replies to this message. All messages\n"
+"received on a connection will have a serial, but messages you haven't\n"
+"sent yet may return 0.\n");
+static PyObject *
+Message_get_serial(Message *self, PyObject *unused UNUSED)
+{
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyLong_FromUnsignedLong(dbus_message_get_serial(self->msg));
+}
+
+PyDoc_STRVAR(Message_is_method_call__doc__,
+"is_method_call(interface: str, member: str) -> bool");
+static PyObject *
+Message_is_method_call(Message *self, PyObject *args)
+{
+ const char *interface, *method;
+
+ if (!PyArg_ParseTuple(args, "ss:is_method_call", &interface, &method)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_is_method_call(self->msg, interface,
+ method));
+}
+
+PyDoc_STRVAR(Message_is_error__doc__,
+"is_error(error: str) -> bool");
+static PyObject *
+Message_is_error(Message *self, PyObject *args)
+{
+ const char *error_name;
+
+ if (!PyArg_ParseTuple(args, "s:is_error", &error_name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_is_error(self->msg, error_name));
+}
+
+PyDoc_STRVAR(Message_is_signal__doc__,
+"is_signal(interface: str, member: str) -> bool");
+static PyObject *
+Message_is_signal(Message *self, PyObject *args)
+{
+ const char *interface, *signal_name;
+
+ if (!PyArg_ParseTuple(args, "ss:is_signal", &interface, &signal_name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_is_signal(self->msg, interface,
+ signal_name));
+}
+
+PyDoc_STRVAR(Message_get_member__doc__,
+"get_member() -> str or None");
+static PyObject *
+Message_get_member(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_member(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyString_FromString(c_str);
+}
+
+PyDoc_STRVAR(Message_has_member__doc__,
+"has_member(name: str or None) -> bool");
+static PyObject *
+Message_has_member(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:has_member", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_member(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_set_member__doc__,
+"set_member(unique_name: str or None)");
+static PyObject *
+Message_set_member(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_member", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_py_validate_member_name(name)) return NULL;
+ if (!dbus_message_set_member(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_path__doc__,
+"get_path() -> ObjectPath or None\n\n"
+"Return the message's destination object path (if it's a method call) or\n"
+"source object path (if it's a method reply or a signal) or None (if it\n"
+"has no path).\n");
+static PyObject *
+Message_get_path(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_path(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyObject_CallFunction((PyObject *)&DBusPyObjectPath_Type, "(s)", c_str);
+}
+
+PyDoc_STRVAR(Message_get_path_decomposed__doc__,
+"get_path_decomposed() -> list of str, or None\n\n"
+"Return a list of path components (e.g. /foo/bar -> ['foo','bar'], / -> [])\n"
+"or None if the message has no associated path.\n");
+static PyObject *
+Message_get_path_decomposed(Message *self, PyObject *unused UNUSED)
+{
+ char **paths, **ptr;
+ PyObject *ret = PyList_New(0);
+
+ if (!ret) return NULL;
+ if (!self->msg) {
+ Py_DECREF(ret);
+ return DBusPy_RaiseUnusableMessage();
+ }
+ if (!dbus_message_get_path_decomposed(self->msg, &paths)) {
+ Py_DECREF(ret);
+ return PyErr_NoMemory();
+ }
+ if (!paths) {
+ Py_DECREF(ret);
+ Py_RETURN_NONE;
+ }
+ for (ptr = paths; *ptr; ptr++) {
+ PyObject *str = PyString_FromString(*ptr);
+
+ if (!str) {
+ Py_DECREF(ret);
+ ret = NULL;
+ break;
+ }
+ if (PyList_Append(ret, str) < 0) {
+ Py_DECREF(ret);
+ ret = NULL;
+ break;
+ }
+ Py_DECREF(str);
+ str = NULL;
+ }
+ dbus_free_string_array(paths);
+ return ret;
+}
+
+PyDoc_STRVAR(Message_has_path__doc__,
+"has_path(name: str or None) -> bool");
+static PyObject *
+Message_has_path(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:has_path", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_path(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_set_path__doc__,
+"set_path(name: str or None)");
+static PyObject *
+Message_set_path(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_path", &name)) return NULL;
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_message_has_path(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_signature__doc__,
+"get_signature() -> Signature or None");
+static PyObject *
+Message_get_signature(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_signature(self->msg);
+ if (!c_str) {
+ return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", "");
+ }
+ return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", c_str);
+}
+
+PyDoc_STRVAR(Message_has_signature__doc__,
+"has_signature(signature: str) -> bool");
+static PyObject *
+Message_has_signature(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:has_signature", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_signature(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_get_sender__doc__,
+"get_sender() -> str or None\n\n"
+"Return the message's sender unique name, or None if none.\n");
+static PyObject *
+Message_get_sender(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_sender(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyString_FromString(c_str);
+}
+
+PyDoc_STRVAR(Message_has_sender__doc__,
+"has_sender(unique_name: str) -> bool");
+static PyObject *
+Message_has_sender(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:has_sender", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_sender(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_set_sender__doc__,
+"set_sender(unique_name: str or None)");
+static PyObject *
+Message_set_sender(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_sender", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_py_validate_bus_name(name, 1, 1)) return NULL;
+ if (!dbus_message_set_sender(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_destination__doc__,
+"get_destination() -> str or None\n\n"
+"Return the message's destination bus name, or None if none.\n");
+static PyObject *
+Message_get_destination(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_destination(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyString_FromString(c_str);
+}
+
+PyDoc_STRVAR(Message_has_destination__doc__,
+"has_destination(bus_name: str) -> bool");
+static PyObject *
+Message_has_destination(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:has_destination", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_destination(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_set_destination__doc__,
+"set_destination(bus_name: str or None)");
+static PyObject *
+Message_set_destination(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_destination", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_py_validate_bus_name(name, 1, 1)) return NULL;
+ if (!dbus_message_set_destination(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_interface__doc__,
+"get_interface() -> str or None");
+static PyObject *
+Message_get_interface(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_interface(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyString_FromString(c_str);
+}
+
+PyDoc_STRVAR(Message_has_interface__doc__,
+"has_interface(interface: str or None) -> bool");
+static PyObject *
+Message_has_interface(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:has_interface", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ return PyBool_FromLong(dbus_message_has_interface(self->msg, name));
+}
+
+PyDoc_STRVAR(Message_set_interface__doc__,
+"set_interface(name: str or None)");
+static PyObject *
+Message_set_interface(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_interface", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_py_validate_interface_name(name)) return NULL;
+ if (!dbus_message_set_interface(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Message_get_error_name__doc__,
+"get_error_name() -> str or None");
+static PyObject *
+Message_get_error_name(Message *self, PyObject *unused UNUSED)
+{
+ const char *c_str;
+
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ c_str = dbus_message_get_error_name(self->msg);
+ if (!c_str) {
+ Py_RETURN_NONE;
+ }
+ return PyString_FromString(c_str);
+}
+
+PyDoc_STRVAR(Message_set_error_name__doc__,
+"set_error_name(name: str or None)");
+static PyObject *
+Message_set_error_name(Message *self, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "z:set_error_name", &name)) {
+ return NULL;
+ }
+ if (!self->msg) return DBusPy_RaiseUnusableMessage();
+ if (!dbus_py_validate_error_name(name)) return NULL;
+ if (!dbus_message_set_error_name(self->msg, name)) return PyErr_NoMemory();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef Message_tp_methods[] = {
+ {"copy", (PyCFunction)Message_copy,
+ METH_NOARGS, Message_copy__doc__},
+ {"is_method_call", (PyCFunction)Message_is_method_call,
+ METH_VARARGS, Message_is_method_call__doc__},
+ {"is_signal", (PyCFunction)Message_is_signal,
+ METH_VARARGS, Message_is_signal__doc__},
+ {"is_error", (PyCFunction)Message_is_error,
+ METH_VARARGS, Message_is_error__doc__},
+
+ {"get_args_list", (PyCFunction)dbus_py_Message_get_args_list,
+ METH_VARARGS|METH_KEYWORDS, dbus_py_Message_get_args_list__doc__},
+ {"guess_signature", (PyCFunction)dbus_py_Message_guess_signature,
+ METH_VARARGS|METH_STATIC, dbus_py_Message_guess_signature__doc__},
+ {"append", (PyCFunction)dbus_py_Message_append,
+ METH_VARARGS|METH_KEYWORDS, dbus_py_Message_append__doc__},
+
+ {"get_auto_start", (PyCFunction)Message_get_auto_start,
+ METH_NOARGS, Message_get_auto_start__doc__},
+ {"set_auto_start", (PyCFunction)Message_set_auto_start,
+ METH_VARARGS, Message_set_auto_start__doc__},
+ {"get_destination", (PyCFunction)Message_get_destination,
+ METH_NOARGS, Message_get_destination__doc__},
+ {"set_destination", (PyCFunction)Message_set_destination,
+ METH_VARARGS, Message_set_destination__doc__},
+ {"has_destination", (PyCFunction)Message_has_destination,
+ METH_VARARGS, Message_has_destination__doc__},
+ {"get_error_name", (PyCFunction)Message_get_error_name,
+ METH_NOARGS, Message_get_error_name__doc__},
+ {"set_error_name", (PyCFunction)Message_set_error_name,
+ METH_VARARGS, Message_set_error_name__doc__},
+ {"get_interface", (PyCFunction)Message_get_interface,
+ METH_NOARGS, Message_get_interface__doc__},
+ {"set_interface", (PyCFunction)Message_set_interface,
+ METH_VARARGS, Message_set_interface__doc__},
+ {"has_interface", (PyCFunction)Message_has_interface,
+ METH_VARARGS, Message_has_interface__doc__},
+ {"get_member", (PyCFunction)Message_get_member,
+ METH_NOARGS, Message_get_member__doc__},
+ {"set_member", (PyCFunction)Message_set_member,
+ METH_VARARGS, Message_set_member__doc__},
+ {"has_member", (PyCFunction)Message_has_member,
+ METH_VARARGS, Message_has_member__doc__},
+ {"get_path", (PyCFunction)Message_get_path,
+ METH_NOARGS, Message_get_path__doc__},
+ {"get_path_decomposed", (PyCFunction)Message_get_path_decomposed,
+ METH_NOARGS, Message_get_path_decomposed__doc__},
+ {"set_path", (PyCFunction)Message_set_path,
+ METH_VARARGS, Message_set_path__doc__},
+ {"has_path", (PyCFunction)Message_has_path,
+ METH_VARARGS, Message_has_path__doc__},
+ {"get_no_reply", (PyCFunction)Message_get_no_reply,
+ METH_NOARGS, Message_get_no_reply__doc__},
+ {"set_no_reply", (PyCFunction)Message_set_no_reply,
+ METH_VARARGS, Message_set_no_reply__doc__},
+ {"get_reply_serial", (PyCFunction)Message_get_reply_serial,
+ METH_NOARGS, Message_get_reply_serial__doc__},
+ {"set_reply_serial", (PyCFunction)Message_set_reply_serial,
+ METH_VARARGS, Message_set_reply_serial__doc__},
+ {"get_sender", (PyCFunction)Message_get_sender,
+ METH_NOARGS, Message_get_sender__doc__},
+ {"set_sender", (PyCFunction)Message_set_sender,
+ METH_VARARGS, Message_set_sender__doc__},
+ {"has_sender", (PyCFunction)Message_has_sender,
+ METH_VARARGS, Message_has_sender__doc__},
+ {"get_serial", (PyCFunction)Message_get_serial,
+ METH_NOARGS, Message_get_serial__doc__},
+ {"get_signature", (PyCFunction)Message_get_signature,
+ METH_NOARGS, Message_get_signature__doc__},
+ {"has_signature", (PyCFunction)Message_has_signature,
+ METH_VARARGS, Message_has_signature__doc__},
+ {"get_type", (PyCFunction)Message_get_type,
+ METH_NOARGS, Message_get_type__doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+static PyTypeObject MessageType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "dbus.lowlevel.Message", /*tp_name*/
+ sizeof(Message), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)Message_tp_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Message_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Message_tp_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Message_tp_new, /* tp_new */
+};
+
+static PyTypeObject MethodCallMessageType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "dbus.lowlevel.MethodCallMessage", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ MethodCallMessage_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&MessageType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)MethodCallMessage_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+static PyTypeObject MethodReturnMessageType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "dbus.lowlevel.MethodReturnMessage", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ MethodReturnMessage_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&MessageType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)MethodReturnMessage_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+static PyTypeObject SignalMessageType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "dbus.lowlevel.SignalMessage", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ SignalMessage_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&MessageType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SignalMessage_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+static PyTypeObject ErrorMessageType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "dbus.lowlevel.ErrorMessage", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ ErrorMessage_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&MessageType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ErrorMessage_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_message_types(void)
+{
+ if (PyType_Ready(&MessageType) < 0) return 0;
+
+ MethodCallMessageType.tp_base = &MessageType;
+ if (PyType_Ready(&MethodCallMessageType) < 0) return 0;
+
+ MethodReturnMessageType.tp_base = &MessageType;
+ if (PyType_Ready(&MethodReturnMessageType) < 0) return 0;
+
+ SignalMessageType.tp_base = &MessageType;
+ if (PyType_Ready(&SignalMessageType) < 0) return 0;
+
+ ErrorMessageType.tp_base = &MessageType;
+ if (PyType_Ready(&ErrorMessageType) < 0) return 0;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_message_types(PyObject *this_module)
+{
+ if (PyModule_AddObject(this_module, "Message",
+ (PyObject *)&MessageType) < 0) return 0;
+
+ if (PyModule_AddObject(this_module, "MethodCallMessage",
+ (PyObject *)&MethodCallMessageType) < 0) return 0;
+
+ if (PyModule_AddObject(this_module, "MethodReturnMessage",
+ (PyObject *)&MethodReturnMessageType) < 0) return 0;
+
+ if (PyModule_AddObject(this_module, "ErrorMessage",
+ (PyObject *)&ErrorMessageType) < 0) return 0;
+
+ if (PyModule_AddObject(this_module, "SignalMessage",
+ (PyObject *)&SignalMessageType) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/module.c b/_dbus_bindings/module.c
new file mode 100644
index 0000000..a4c2a66
--- /dev/null
+++ b/_dbus_bindings/module.c
@@ -0,0 +1,395 @@
+/* Main module source for the _dbus_bindings extension.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "config.h"
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "dbus_bindings-internal.h"
+
+PyDoc_STRVAR(module_doc,
+"Low-level Python bindings for libdbus. Don't use this module directly -\n"
+"the public API is provided by the `dbus`, `dbus.service`, `dbus.mainloop`\n"
+"and `dbus.mainloop.glib` modules, with a lower-level API provided by the\n"
+"`dbus.lowlevel` module.\n"
+);
+
+/* Global functions - validation wrappers ===========================*/
+
+PyDoc_STRVAR(validate_bus_name__doc__,
+"validate_bus_name(name, allow_unique=True, allow_well_known=True)\n"
+"\n"
+"Raise ValueError if the argument is not a valid bus name.\n"
+"\n"
+"By default both unique and well-known names are accepted.\n"
+"\n"
+":Parameters:\n"
+" `name` : str\n"
+" The name to be validated\n"
+" `allow_unique` : bool\n"
+" If False, unique names of the form :1.123 will be rejected\n"
+" `allow_well_known` : bool\n"
+" If False, well-known names of the form com.example.Foo\n"
+" will be rejected\n"
+":Since: 0.80\n"
+);
+
+static PyObject *
+validate_bus_name(PyObject *unused UNUSED, PyObject *args, PyObject *kwargs)
+{
+ const char *name;
+ int allow_unique = 1;
+ int allow_well_known = 1;
+ static char *argnames[] = { "name", "allow_unique", "allow_well_known",
+ NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "s|ii:validate_bus_name", argnames,
+ &name, &allow_unique,
+ &allow_well_known)) {
+ return NULL;
+ }
+ if (!dbus_py_validate_bus_name(name, !!allow_unique, !!allow_well_known)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(validate_member_name__doc__,
+"validate_member_name(name)\n"
+"\n"
+"Raise ValueError if the argument is not a valid member (signal or method) "
+"name.\n"
+"\n"
+":Since: 0.80\n"
+);
+
+static PyObject *
+validate_member_name(PyObject *unused UNUSED, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:validate_member_name", &name)) {
+ return NULL;
+ }
+ if (!dbus_py_validate_member_name(name)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(validate_interface_name__doc__,
+"validate_interface_name(name)\n\n"
+"Raise ValueError if the given string is not a valid interface name.\n"
+"\n"
+":Since: 0.80\n"
+);
+
+PyDoc_STRVAR(validate_error_name__doc__,
+"validate_error_name(name)\n\n"
+"Raise ValueError if the given string is not a valid error name.\n"
+"\n"
+":Since: 0.80\n"
+);
+
+static PyObject *
+validate_interface_name(PyObject *unused UNUSED, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:validate_interface_name", &name)) {
+ return NULL;
+ }
+ if (!dbus_py_validate_interface_name(name)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(validate_object_path__doc__,
+"validate_object_path(name)\n\n"
+"Raise ValueError if the given string is not a valid object path.\n"
+"\n"
+":Since: 0.80\n"
+);
+
+static PyObject *
+validate_object_path(PyObject *unused UNUSED, PyObject *args)
+{
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:validate_object_path", &name)) {
+ return NULL;
+ }
+ if (!dbus_py_validate_object_path(name)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/* Global functions - main loop =====================================*/
+
+/* The main loop if none is passed to the constructor */
+static PyObject *default_main_loop = NULL;
+
+/* Return a new reference to the default main loop */
+PyObject *
+dbus_py_get_default_main_loop(void)
+{
+ if (!default_main_loop) {
+ Py_RETURN_NONE;
+ }
+ Py_INCREF(default_main_loop);
+ return default_main_loop;
+}
+
+PyDoc_STRVAR(get_default_main_loop__doc__,
+"get_default_main_loop() -> object\n\n"
+"Return the global default dbus-python main loop wrapper, which is used\n"
+"when no main loop wrapper is passed to the Connection constructor.\n"
+"\n"
+"If None, there is no default and you should always pass the mainloop\n"
+"parameter to the constructor - if you don't, then asynchronous calls,\n"
+"connecting to signals and exporting objects will raise an exception.\n"
+"There is no default until set_default_main_loop is called.\n");
+static PyObject *
+get_default_main_loop(PyObject *always_null UNUSED,
+ PyObject *no_args UNUSED)
+{
+ return dbus_py_get_default_main_loop();
+}
+
+PyDoc_STRVAR(set_default_main_loop__doc__,
+"set_default_main_loop(object)\n\n"
+"Change the global default dbus-python main loop wrapper, which is used\n"
+"when no main loop wrapper is passed to the Connection constructor.\n"
+"\n"
+"If None, return to the initial situation: there is no default, and you\n"
+"must always pass the mainloop parameter to the constructor.\n"
+"\n"
+"Two types of main loop wrapper are planned in dbus-python.\n"
+"Native main-loop wrappers are instances of `dbus.mainloop.NativeMainLoop`\n"
+"supplied by extension modules like `dbus.mainloop.glib`: they have no\n"
+"Python API, but connect themselves to ``libdbus`` using native code.\n"
+
+"Python main-loop wrappers are not yet implemented. They will be objects\n"
+"supporting the interface defined by `dbus.mainloop.MainLoop`, with an\n"
+"API entirely based on Python methods.\n"
+"\n"
+);
+static PyObject *
+set_default_main_loop(PyObject *always_null UNUSED,
+ PyObject *args)
+{
+ PyObject *new_loop, *old_loop;
+
+ if (!PyArg_ParseTuple(args, "O", &new_loop)) {
+ return NULL;
+ }
+ if (!dbus_py_check_mainloop_sanity(new_loop)) {
+ return NULL;
+ }
+ old_loop = default_main_loop;
+ Py_INCREF(new_loop);
+ default_main_loop = new_loop;
+ Py_XDECREF(old_loop);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef module_functions[] = {
+#define ENTRY(name,flags) {#name, (PyCFunction)name, flags, name##__doc__}
+ ENTRY(validate_interface_name, METH_VARARGS),
+ ENTRY(validate_member_name, METH_VARARGS),
+ ENTRY(validate_bus_name, METH_VARARGS|METH_KEYWORDS),
+ ENTRY(validate_object_path, METH_VARARGS),
+ ENTRY(set_default_main_loop, METH_VARARGS),
+ ENTRY(get_default_main_loop, METH_NOARGS),
+ /* validate_error_name is just implemented as validate_interface_name */
+ {"validate_error_name", validate_interface_name,
+ METH_VARARGS, validate_error_name__doc__},
+#undef ENTRY
+ {NULL, NULL, 0, NULL}
+};
+
+PyMODINIT_FUNC
+init_dbus_bindings(void)
+{
+ PyObject *this_module, *c_api;
+ static const int API_count = DBUS_BINDINGS_API_COUNT;
+ static _dbus_py_func_ptr dbus_bindings_API[DBUS_BINDINGS_API_COUNT];
+
+ dbus_bindings_API[0] = (_dbus_py_func_ptr)&API_count;
+ dbus_bindings_API[1] = (_dbus_py_func_ptr)DBusPyConnection_BorrowDBusConnection;
+ dbus_bindings_API[2] = (_dbus_py_func_ptr)DBusPyNativeMainLoop_New4;
+
+ default_main_loop = NULL;
+
+ /* I'd rather not initialize threads if we can help it - dbus-python and
+ pygobject both release and re-obtain the GIL on a regular basis, which is
+ much simpler (basically free) before threads are initialized.
+
+ However, on Python < 2.4.2c1 you aren't allowed to call
+ PyGILState_Release without initializing threads first. */
+ if (strcmp(Py_GetVersion(), "2.4.2c1") < 0) {
+ PyEval_InitThreads();
+ }
+
+ if (!dbus_py_init_generic()) return;
+ if (!dbus_py_init_abstract()) return;
+ if (!dbus_py_init_signature()) return;
+ if (!dbus_py_init_int_types()) return;
+ if (!dbus_py_init_string_types()) return;
+ if (!dbus_py_init_float_types()) return;
+ if (!dbus_py_init_container_types()) return;
+ if (!dbus_py_init_byte_types()) return;
+ if (!dbus_py_init_message_types()) return;
+ if (!dbus_py_init_pending_call()) return;
+ if (!dbus_py_init_mainloop()) return;
+ if (!dbus_py_init_libdbus_conn_types()) return;
+ if (!dbus_py_init_conn_types()) return;
+ if (!dbus_py_init_server_types()) return;
+
+ this_module = Py_InitModule3("_dbus_bindings", module_functions, module_doc);
+ if (!this_module) return;
+
+ if (!dbus_py_insert_abstract_types(this_module)) return;
+ if (!dbus_py_insert_signature(this_module)) return;
+ if (!dbus_py_insert_int_types(this_module)) return;
+ if (!dbus_py_insert_string_types(this_module)) return;
+ if (!dbus_py_insert_float_types(this_module)) return;
+ if (!dbus_py_insert_container_types(this_module)) return;
+ if (!dbus_py_insert_byte_types(this_module)) return;
+ if (!dbus_py_insert_message_types(this_module)) return;
+ if (!dbus_py_insert_pending_call(this_module)) return;
+ if (!dbus_py_insert_mainloop_types(this_module)) return;
+ if (!dbus_py_insert_libdbus_conn_types(this_module)) return;
+ if (!dbus_py_insert_conn_types(this_module)) return;
+ if (!dbus_py_insert_server_types(this_module)) return;
+
+ if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_NAME",
+ DBUS_SERVICE_DBUS) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_PATH",
+ DBUS_PATH_DBUS) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_IFACE",
+ DBUS_INTERFACE_DBUS) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "LOCAL_PATH",
+ DBUS_PATH_LOCAL) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "LOCAL_IFACE",
+ DBUS_INTERFACE_LOCAL) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "INTROSPECTABLE_IFACE",
+ DBUS_INTERFACE_INTROSPECTABLE) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "PEER_IFACE",
+ DBUS_INTERFACE_PEER) < 0) return;
+ if (PyModule_AddStringConstant(this_module, "PROPERTIES_IFACE",
+ DBUS_INTERFACE_PROPERTIES) < 0) return;
+ if (PyModule_AddStringConstant(this_module,
+ "DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER",
+ DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER) < 0) return;
+ if (PyModule_AddStringConstant(this_module,
+ "DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER",
+ DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER) < 0) return;
+ if (PyModule_AddStringConstant(this_module,
+ "DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE",
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE) < 0) return;
+
+#define ADD_CONST_VAL(x, v) \
+ if (PyModule_AddIntConstant(this_module, x, v) < 0) return;
+#define ADD_CONST_PREFIXED(x) ADD_CONST_VAL(#x, DBUS_##x)
+#define ADD_CONST(x) ADD_CONST_VAL(#x, x)
+
+ ADD_CONST(DBUS_START_REPLY_SUCCESS)
+ ADD_CONST(DBUS_START_REPLY_ALREADY_RUNNING)
+
+ ADD_CONST_PREFIXED(RELEASE_NAME_REPLY_RELEASED)
+ ADD_CONST_PREFIXED(RELEASE_NAME_REPLY_NON_EXISTENT)
+ ADD_CONST_PREFIXED(RELEASE_NAME_REPLY_NOT_OWNER)
+
+ ADD_CONST_PREFIXED(REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ ADD_CONST_PREFIXED(REQUEST_NAME_REPLY_IN_QUEUE)
+ ADD_CONST_PREFIXED(REQUEST_NAME_REPLY_EXISTS)
+ ADD_CONST_PREFIXED(REQUEST_NAME_REPLY_ALREADY_OWNER)
+
+ ADD_CONST_PREFIXED(NAME_FLAG_ALLOW_REPLACEMENT)
+ ADD_CONST_PREFIXED(NAME_FLAG_REPLACE_EXISTING)
+ ADD_CONST_PREFIXED(NAME_FLAG_DO_NOT_QUEUE)
+
+ ADD_CONST_PREFIXED(BUS_SESSION)
+ ADD_CONST_PREFIXED(BUS_SYSTEM)
+ ADD_CONST_PREFIXED(BUS_STARTER)
+
+ ADD_CONST_PREFIXED(MESSAGE_TYPE_INVALID)
+ ADD_CONST_PREFIXED(MESSAGE_TYPE_METHOD_CALL)
+ ADD_CONST_PREFIXED(MESSAGE_TYPE_METHOD_RETURN)
+ ADD_CONST_PREFIXED(MESSAGE_TYPE_ERROR)
+ ADD_CONST_PREFIXED(MESSAGE_TYPE_SIGNAL)
+
+ ADD_CONST_PREFIXED(TYPE_INVALID)
+ ADD_CONST_PREFIXED(TYPE_BYTE)
+ ADD_CONST_PREFIXED(TYPE_BOOLEAN)
+ ADD_CONST_PREFIXED(TYPE_INT16)
+ ADD_CONST_PREFIXED(TYPE_UINT16)
+ ADD_CONST_PREFIXED(TYPE_INT32)
+ ADD_CONST_PREFIXED(TYPE_UINT32)
+ ADD_CONST_PREFIXED(TYPE_INT64)
+ ADD_CONST_PREFIXED(TYPE_UINT64)
+ ADD_CONST_PREFIXED(TYPE_DOUBLE)
+ ADD_CONST_PREFIXED(TYPE_STRING)
+ ADD_CONST_PREFIXED(TYPE_OBJECT_PATH)
+ ADD_CONST_PREFIXED(TYPE_SIGNATURE)
+ ADD_CONST_PREFIXED(TYPE_ARRAY)
+ ADD_CONST_PREFIXED(TYPE_STRUCT)
+ ADD_CONST_VAL("STRUCT_BEGIN", DBUS_STRUCT_BEGIN_CHAR)
+ ADD_CONST_VAL("STRUCT_END", DBUS_STRUCT_END_CHAR)
+ ADD_CONST_PREFIXED(TYPE_VARIANT)
+ ADD_CONST_PREFIXED(TYPE_DICT_ENTRY)
+ ADD_CONST_VAL("DICT_ENTRY_BEGIN", DBUS_DICT_ENTRY_BEGIN_CHAR)
+ ADD_CONST_VAL("DICT_ENTRY_END", DBUS_DICT_ENTRY_END_CHAR)
+
+ ADD_CONST_PREFIXED(HANDLER_RESULT_HANDLED)
+ ADD_CONST_PREFIXED(HANDLER_RESULT_NOT_YET_HANDLED)
+ ADD_CONST_PREFIXED(HANDLER_RESULT_NEED_MEMORY)
+
+ ADD_CONST_PREFIXED(WATCH_READABLE)
+ ADD_CONST_PREFIXED(WATCH_WRITABLE)
+ ADD_CONST_PREFIXED(WATCH_HANGUP)
+ ADD_CONST_PREFIXED(WATCH_ERROR)
+
+ if (PyModule_AddStringConstant(this_module, "__docformat__",
+ "restructuredtext") < 0) return;
+
+ if (PyModule_AddStringConstant(this_module, "__version__",
+ PACKAGE_VERSION) < 0) return;
+
+ if (PyModule_AddIntConstant(this_module, "_python_version",
+ PY_VERSION_HEX) < 0) return;
+
+ c_api = PyCObject_FromVoidPtr ((void *)dbus_bindings_API, NULL);
+ if (!c_api) {
+ return;
+ }
+ PyModule_AddObject(this_module, "_C_API", c_api);
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/pending-call.c b/_dbus_bindings/pending-call.c
new file mode 100644
index 0000000..ad18fd7
--- /dev/null
+++ b/_dbus_bindings/pending-call.c
@@ -0,0 +1,293 @@
+/* Implementation of PendingCall helper type for D-Bus bindings.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+
+PyDoc_STRVAR(PendingCall_tp_doc,
+"Object representing a pending D-Bus call, returned by\n"
+"Connection.send_message_with_reply(). Cannot be instantiated directly.\n"
+);
+
+static PyTypeObject PendingCallType;
+
+static inline int PendingCall_Check (PyObject *o)
+{
+ return (o->ob_type == &PendingCallType)
+ || PyObject_IsInstance(o, (PyObject *)&PendingCallType);
+}
+
+typedef struct {
+ PyObject_HEAD
+ DBusPendingCall *pc;
+} PendingCall;
+
+PyDoc_STRVAR(PendingCall_cancel__doc__,
+"cancel()\n\n"
+"Cancel this pending call. Its reply will be ignored and the associated\n"
+"reply handler will never be called.\n");
+static PyObject *
+PendingCall_cancel(PendingCall *self, PyObject *unused UNUSED)
+{
+ Py_BEGIN_ALLOW_THREADS
+ dbus_pending_call_cancel(self->pc);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(PendingCall_block__doc__,
+"block()\n\n"
+"Block until this pending call has completed and the associated\n"
+"reply handler has been called.\n"
+"\n"
+"This can lead to a deadlock, if the called method tries to make a\n"
+"synchronous call to a method in this application.\n");
+static PyObject *
+PendingCall_block(PendingCall *self, PyObject *unused UNUSED)
+{
+ Py_BEGIN_ALLOW_THREADS
+ dbus_pending_call_block(self->pc);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+static void
+_pending_call_notify_function(DBusPendingCall *pc,
+ PyObject *list)
+{
+ PyGILState_STATE gil = PyGILState_Ensure();
+ /* BEGIN CRITICAL SECTION
+ * While holding the GIL, make sure the callback only gets called once
+ * by deleting it from the 1-item list that's held by libdbus.
+ */
+ PyObject *handler = PyList_GetItem(list, 0);
+ DBusMessage *msg;
+
+ if (!handler) {
+ PyErr_Print();
+ goto release;
+ }
+ if (handler == Py_None) {
+ /* We've already called (and thrown away) the callback */
+ goto release;
+ }
+ Py_INCREF(handler); /* previously borrowed from the list, now owned */
+ Py_INCREF(Py_None); /* take a ref so SetItem can steal it */
+ PyList_SetItem(list, 0, Py_None);
+ /* END CRITICAL SECTION */
+
+ msg = dbus_pending_call_steal_reply(pc);
+
+ if (!msg) {
+ /* omg, what happened here? the notify should only get called
+ * when we have a reply */
+ PyErr_Warn(PyExc_UserWarning, "D-Bus notify function was called "
+ "for an incomplete pending call (shouldn't happen)");
+ } else {
+ PyObject *msg_obj = DBusPyMessage_ConsumeDBusMessage(msg);
+
+ if (msg_obj) {
+ PyObject *ret = PyObject_CallFunctionObjArgs(handler, msg_obj, NULL);
+
+ if (!ret) {
+ PyErr_Print();
+ }
+ Py_XDECREF(ret);
+ Py_DECREF(msg_obj);
+ }
+ /* else OOM has happened - not a lot we can do about that,
+ * except possibly making it fatal (FIXME?) */
+ }
+
+release:
+ Py_XDECREF(handler);
+ PyGILState_Release(gil);
+}
+
+PyDoc_STRVAR(PendingCall_get_completed__doc__,
+"get_completed() -> bool\n\n"
+"Return true if this pending call has completed.\n\n"
+"If so, its associated reply handler has been called and it is no\n"
+"longer meaningful to cancel it.\n");
+static PyObject *
+PendingCall_get_completed(PendingCall *self, PyObject *unused UNUSED)
+{
+ dbus_bool_t ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_pending_call_get_completed(self->pc);
+ Py_END_ALLOW_THREADS
+ return PyBool_FromLong(ret);
+}
+
+/* Steals the reference to the pending call. */
+PyObject *
+DBusPyPendingCall_ConsumeDBusPendingCall(DBusPendingCall *pc,
+ PyObject *callable)
+{
+ dbus_bool_t ret;
+ PyObject *list = PyList_New(1);
+ PendingCall *self = PyObject_New(PendingCall, &PendingCallType);
+
+ if (!list || !self) {
+ Py_XDECREF(list);
+ Py_XDECREF(self);
+ Py_BEGIN_ALLOW_THREADS
+ dbus_pending_call_cancel(pc);
+ dbus_pending_call_unref(pc);
+ Py_END_ALLOW_THREADS
+ return NULL;
+ }
+
+ /* INCREF because SET_ITEM steals a ref */
+ Py_INCREF(callable);
+ PyList_SET_ITEM(list, 0, callable);
+
+ /* INCREF so we can give a ref to set_notify and still have one */
+ Py_INCREF(list);
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_pending_call_set_notify(pc,
+ (DBusPendingCallNotifyFunction)_pending_call_notify_function,
+ (void *)list, (DBusFreeFunction)dbus_py_take_gil_and_xdecref);
+ Py_END_ALLOW_THREADS
+
+ if (!ret) {
+ PyErr_NoMemory();
+ /* DECREF twice - one for the INCREF and one for the allocation */
+ Py_DECREF(list);
+ Py_DECREF(list);
+ Py_DECREF(self);
+ Py_BEGIN_ALLOW_THREADS
+ dbus_pending_call_cancel(pc);
+ dbus_pending_call_unref(pc);
+ Py_END_ALLOW_THREADS
+ return NULL;
+ }
+
+ /* As Alexander Larsson pointed out on dbus@lists.fd.o on 2006-11-30,
+ * the API has a race condition if set_notify runs in one thread and a
+ * mail loop runs in another - if the reply gets in before set_notify
+ * runs, the notify isn't called and there is no indication of error.
+ *
+ * The workaround is to check for completion immediately, but this also
+ * has a race which might lead to getting the notify called twice if
+ * we're unlucky. So I use the list to arrange for the notify to be
+ * deleted before it's called for the second time. The GIL protects
+ * the critical section in which I delete the callback from the list.
+ */
+ if (dbus_pending_call_get_completed(pc)) {
+ /* the first race condition happened, so call the callable here.
+ * FIXME: we ought to arrange for the callable to run from the
+ * mainloop thread, like it would if the race hadn't happened...
+ * this needs a better mainloop abstraction, though.
+ */
+ _pending_call_notify_function(pc, list);
+ }
+
+ Py_DECREF(list);
+ self->pc = pc;
+ return (PyObject *)self;
+}
+
+static void
+PendingCall_tp_dealloc (PendingCall *self)
+{
+ if (self->pc) {
+ Py_BEGIN_ALLOW_THREADS
+ dbus_pending_call_unref(self->pc);
+ Py_END_ALLOW_THREADS
+ }
+ PyObject_Del (self);
+}
+
+static PyMethodDef PendingCall_tp_methods[] = {
+ {"block", (PyCFunction)PendingCall_block, METH_NOARGS,
+ PendingCall_block__doc__},
+ {"cancel", (PyCFunction)PendingCall_cancel, METH_NOARGS,
+ PendingCall_cancel__doc__},
+ {"get_completed", (PyCFunction)PendingCall_get_completed, METH_NOARGS,
+ PendingCall_get_completed__doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+static PyTypeObject PendingCallType = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.lowlevel.PendingCall",
+ sizeof(PendingCall),
+ 0,
+ (destructor)PendingCall_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ PendingCall_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ PendingCall_tp_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ /* deliberately not callable! Use PendingCall_ConsumeDBusPendingCall */
+ 0, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_pending_call (void)
+{
+ if (PyType_Ready (&PendingCallType) < 0) return 0;
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_pending_call (PyObject *this_module)
+{
+ if (PyModule_AddObject (this_module, "PendingCall",
+ (PyObject *)&PendingCallType) < 0) return 0;
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/server.c b/_dbus_bindings/server.c
new file mode 100644
index 0000000..7fc4f70
--- /dev/null
+++ b/_dbus_bindings/server.c
@@ -0,0 +1,581 @@
+/* Implementation of the _dbus_bindings Server type, a Python wrapper
+ * for DBusServer.
+ *
+ * Copyright (C) 2008 Openismus GmbH <http://openismus.com/>
+ * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+
+/* Server definition ================================================ */
+
+typedef struct {
+ PyObject_HEAD
+ DBusServer *server;
+
+ /* The Connection subtype for which this Server is a factory */
+ PyObject *conn_class;
+
+ /* Weak-references list to make server weakly referenceable */
+ PyObject *weaklist;
+
+ PyObject *mainloop;
+} Server;
+
+PyDoc_STRVAR(Server_tp_doc,
+"A D-Bus server.\n"
+"\n"
+"::\n"
+"\n"
+" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n"
+" -> Server\n"
+);
+
+/* D-Bus Server user data slot, containing an owned reference to either
+ * the Server, or a weakref to the Server.
+ */
+static dbus_int32_t _server_python_slot;
+
+/* C API for main-loop hooks ======================================== */
+
+/* Return a borrowed reference to the DBusServer which underlies this
+ * Server. */
+DBusServer *
+DBusPyServer_BorrowDBusServer(PyObject *self)
+{
+ DBusServer *dbs;
+
+ TRACE(self);
+ if (!DBusPyServer_Check(self)) {
+ PyErr_SetString(PyExc_TypeError, "A dbus.server.Server is required");
+ return NULL;
+ }
+ dbs = ((Server *)self)->server;
+ if (!dbs) {
+ PyErr_SetString(PyExc_RuntimeError, "Server is in an invalid "
+ "state: no DBusServer");
+ return NULL;
+ }
+ return dbs;
+}
+
+/* Internal C API =================================================== */
+
+static dbus_bool_t
+DBusPyServer_set_auth_mechanisms(Server *self,
+ PyObject *auth_mechanisms)
+{
+ PyObject *fast_seq;
+ Py_ssize_t length;
+ Py_ssize_t i;
+
+ fast_seq = PySequence_Fast(auth_mechanisms,
+ "Expecting sequence for auth_mechanisms parameter");
+
+ if (!fast_seq)
+ return FALSE;
+
+ length = PySequence_Fast_GET_SIZE(fast_seq);
+
+ /* scope for list */
+ {
+ const char *list[length + 1];
+
+ for (i = 0; i < length; ++i) {
+ PyObject *am;
+
+ am = PySequence_Fast_GET_ITEM(auth_mechanisms, i);
+ /* this supports either str or unicode, raising TypeError
+ * on failure */
+ list[i] = PyString_AsString(am);
+
+ if (!list[i])
+ return FALSE;
+ }
+
+ list[length] = NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ dbus_server_set_auth_mechanisms(self->server, list);
+ Py_END_ALLOW_THREADS
+ }
+
+ return TRUE;
+}
+
+/* Return a new reference to a Python Server or subclass corresponding
+ * to the DBusServer server. For use in callbacks.
+ *
+ * Raises AssertionError if the DBusServer does not have a Server.
+ */
+static PyObject *
+DBusPyServer_ExistingFromDBusServer(DBusServer *server)
+{
+ PyObject *self, *ref;
+
+ Py_BEGIN_ALLOW_THREADS
+ ref = (PyObject *)dbus_server_get_data(server,
+ _server_python_slot);
+ Py_END_ALLOW_THREADS
+ if (ref) {
+ DBG("(DBusServer *)%p has weak reference at %p", server, ref);
+ self = PyWeakref_GetObject(ref); /* still a borrowed ref */
+ if (self && self != Py_None && DBusPyServer_Check(self)) {
+ DBG("(DBusServer *)%p has weak reference at %p pointing to %p",
+ server, ref, self);
+ TRACE(self);
+ Py_INCREF(self);
+ TRACE(self);
+ return self;
+ }
+ }
+
+ PyErr_SetString(PyExc_AssertionError,
+ "D-Bus server does not have a Server "
+ "instance associated with it");
+ return NULL;
+}
+
+static void
+DBusPyServer_new_connection_cb(DBusServer *server,
+ DBusConnection *conn,
+ void *data UNUSED)
+{
+ PyGILState_STATE gil = PyGILState_Ensure();
+ PyObject *self = NULL;
+ PyObject *method = NULL;
+
+ self = DBusPyServer_ExistingFromDBusServer(server);
+ if (!self) goto out;
+ TRACE(self);
+
+ method = PyObject_GetAttrString(self, "_on_new_connection");
+ TRACE(method);
+
+ if (method) {
+ PyObject *conn_class = ((Server *)self)->conn_class;
+ PyObject *wrapper = DBusPyLibDBusConnection_New(conn);
+ PyObject *conn_obj;
+ PyObject *result;
+
+ if (!wrapper)
+ goto out;
+
+ conn_obj = PyObject_CallFunctionObjArgs((PyObject *)conn_class,
+ wrapper, ((Server*) self)->mainloop, NULL);
+ Py_DECREF(wrapper);
+
+ if (!conn_obj)
+ goto out;
+
+ result = PyObject_CallFunctionObjArgs(method, conn_obj, NULL);
+ Py_XDECREF (conn_obj);
+
+ /* discard result if not NULL, and fall through regardless */
+ Py_XDECREF(result);
+ }
+
+out:
+ Py_XDECREF(method);
+ Py_XDECREF(self);
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+
+ PyGILState_Release(gil);
+}
+
+/* Return a new reference to a Python Server or subclass (given by cls)
+ * corresponding to the DBusServer server, which must have been newly
+ * created. For use by the Server constructor.
+ *
+ * Raises AssertionError if the DBusServer already has a Server.
+ *
+ * One reference to server is stolen - either the returned DBusPyServer
+ * claims it, or it's unreffed.
+ */
+static PyObject *
+DBusPyServer_NewConsumingDBusServer(PyTypeObject *cls,
+ DBusServer *server,
+ PyObject *conn_class,
+ PyObject *mainloop,
+ PyObject *auth_mechanisms)
+{
+ Server *self = NULL;
+ PyObject *ref;
+ dbus_bool_t ok;
+
+ DBG("%s(cls=%p, server=%p, mainloop=%p, auth_mechanisms=%p)",
+ __func__, cls, server, mainloop, auth_mechanisms);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(server);
+
+ Py_BEGIN_ALLOW_THREADS
+ ref = (PyObject *)dbus_server_get_data(server,
+ _server_python_slot);
+ Py_END_ALLOW_THREADS
+ if (ref) {
+ self = (Server *)PyWeakref_GetObject(ref);
+ ref = NULL;
+ if (self && (PyObject *)self != Py_None) {
+ self = NULL;
+ PyErr_SetString(PyExc_AssertionError,
+ "Newly created D-Bus server already has a "
+ "Server instance associated with it");
+ DBG("%s() fail - assertion failed, DBusPyServer has a DBusServer already", __func__);
+ DBG_WHEREAMI;
+ return NULL;
+ }
+ }
+ ref = NULL;
+
+ /* Change mainloop from a borrowed reference to an owned reference */
+ if (!mainloop || mainloop == Py_None) {
+ mainloop = dbus_py_get_default_main_loop();
+
+ if (!mainloop || mainloop == Py_None) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "To run a D-Bus server, you need to either "
+ "pass mainloop=... to the constructor or call "
+ "dbus.set_default_main_loop(...)");
+ goto err;
+ }
+ }
+ else {
+ Py_INCREF(mainloop);
+ }
+
+ DBG("Constructing Server from DBusServer at %p", server);
+
+ self = (Server *)(cls->tp_alloc(cls, 0));
+ if (!self) goto err;
+ TRACE(self);
+
+ DBG_WHEREAMI;
+
+ self->server = NULL;
+
+ Py_INCREF(conn_class);
+ self->conn_class = conn_class;
+
+ self->mainloop = mainloop;
+ mainloop = NULL; /* don't DECREF it - the DBusServer owns it now */
+
+ ref = PyWeakref_NewRef((PyObject *)self, NULL);
+ if (!ref) goto err;
+ DBG("Created weak ref %p to (Server *)%p for (DBusServer *)%p",
+ ref, self, server);
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = dbus_server_set_data(server, _server_python_slot,
+ (void *)ref,
+ (DBusFreeFunction)dbus_py_take_gil_and_xdecref);
+ Py_END_ALLOW_THREADS
+
+ if (ok) {
+ DBG("Attached weak ref %p ((Server *)%p) to (DBusServer *)%p",
+ ref, self, server);
+
+ ref = NULL; /* don't DECREF it - the DBusServer owns it now */
+ }
+ else {
+ DBG("Failed to attached weak ref %p ((Server *)%p) to "
+ "(DBusServer *)%p - will dispose of it", ref, self, server);
+ PyErr_NoMemory();
+ goto err;
+ }
+
+ DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(server, err);
+ self->server = server;
+ /* the DBusPyServer will close it now */
+ server = NULL;
+
+ if (self->mainloop != Py_None &&
+ !dbus_py_set_up_server((PyObject *)self, self->mainloop))
+ goto err;
+
+ if (auth_mechanisms && auth_mechanisms != Py_None &&
+ !DBusPyServer_set_auth_mechanisms(self, auth_mechanisms))
+ goto err;
+
+ Py_BEGIN_ALLOW_THREADS
+ dbus_server_set_new_connection_function(self->server,
+ DBusPyServer_new_connection_cb,
+ NULL, NULL);
+ Py_END_ALLOW_THREADS
+
+ DBG("%s() -> %p", __func__, self);
+ TRACE(self);
+ return (PyObject *)self;
+
+err:
+ DBG("Failed to construct Server from DBusServer at %p", server);
+ Py_XDECREF(mainloop);
+ Py_XDECREF(self);
+ Py_XDECREF(ref);
+
+ if (server) {
+ Py_BEGIN_ALLOW_THREADS
+ dbus_server_disconnect(server);
+ dbus_server_unref(server);
+ Py_END_ALLOW_THREADS
+ }
+
+ DBG("%s() fail", __func__);
+ DBG_WHEREAMI;
+ return NULL;
+}
+
+/* Server type-methods ============================================== */
+
+static PyObject *
+Server_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ DBusServer *server;
+ const char *address;
+ DBusError error;
+ PyObject *self, *conn_class, *mainloop = NULL, *auth_mechanisms = NULL;
+ static char *argnames[] = { "address", "connection_class", "mainloop",
+ "auth_mechanisms", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OO", argnames,
+ &address, &conn_class, &mainloop, &auth_mechanisms)) {
+ return NULL;
+ }
+
+ if (!PyType_Check(conn_class) ||
+ !PyType_IsSubtype((PyTypeObject *) conn_class, &DBusPyConnection_Type)) {
+ /* strictly speaking, it can be any subtype of
+ * _dbus_bindings._Connection - but nobody else should be subtyping
+ * that, so let's keep this slightly inaccurate message */
+ PyErr_SetString(PyExc_TypeError, "connection_class must be "
+ "dbus.connection.Connection or a subtype");
+ return NULL;
+ }
+
+ dbus_error_init(&error);
+
+ Py_BEGIN_ALLOW_THREADS
+ server = dbus_server_listen(address, &error);
+ Py_END_ALLOW_THREADS
+
+ if (!server) {
+ DBusPyException_ConsumeError(&error);
+ return NULL;
+ }
+
+ self = DBusPyServer_NewConsumingDBusServer(cls, server, conn_class,
+ mainloop, auth_mechanisms);
+ TRACE(self);
+
+ return self;
+}
+
+/* Destructor */
+static void Server_tp_dealloc(Server *self)
+{
+ DBusServer *server = self->server;
+ PyObject *et, *ev, *etb;
+
+ /* avoid clobbering any pending exception */
+ PyErr_Fetch(&et, &ev, &etb);
+
+ if (self->weaklist) {
+ PyObject_ClearWeakRefs((PyObject *)self);
+ }
+
+ TRACE(self);
+ DBG("Deallocating Server at %p (DBusServer at %p)", self, server);
+ DBG_WHEREAMI;
+
+ if (server) {
+ DBG("Server at %p has a server, disconnecting it...", self);
+ Py_BEGIN_ALLOW_THREADS
+ dbus_server_disconnect(server);
+ Py_END_ALLOW_THREADS
+ }
+
+ Py_DECREF(self->mainloop);
+
+ /* make sure to do this last to preserve the invariant that
+ * self->server is always non-NULL for any referenced Server.
+ */
+ DBG("Server at %p: nulling self->server", self);
+ self->server = NULL;
+
+ if (server) {
+ DBG("Server at %p: unreffing server", self);
+ dbus_server_unref(server);
+ }
+
+ DBG("Server at %p: freeing self", self);
+ PyErr_Restore(et, ev, etb);
+ (self->ob_type->tp_free)((PyObject *)self);
+}
+
+PyDoc_STRVAR(Server_disconnect__doc__,
+"disconnect()\n\n"
+"Releases the server's address and stops listening for new clients.\n\n"
+"If called more than once, only the first call has an effect.");
+static PyObject *
+Server_disconnect (Server *self, PyObject *args UNUSED)
+{
+ TRACE(self);
+ if (self->server) {
+ Py_BEGIN_ALLOW_THREADS
+ dbus_server_disconnect(self->server);
+ Py_END_ALLOW_THREADS
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Server_get_address__doc__,
+"get_address() -> str\n\n"
+"Returns the address of the server.");
+static PyObject *
+Server_get_address(Server *self, PyObject *args UNUSED)
+{
+ const char *address;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
+ Py_BEGIN_ALLOW_THREADS
+ address = dbus_server_get_address(self->server);
+ Py_END_ALLOW_THREADS
+
+ return PyString_FromString(address);
+}
+
+PyDoc_STRVAR(Server_get_id__doc__,
+"get_id() -> str\n\n"
+"Returns the unique ID of the server.");
+static PyObject *
+Server_get_id(Server *self, PyObject *args UNUSED)
+{
+ const char *id;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
+ Py_BEGIN_ALLOW_THREADS
+ id = dbus_server_get_id(self->server);
+ Py_END_ALLOW_THREADS
+
+ return PyString_FromString(id);
+}
+
+PyDoc_STRVAR(Server_get_is_connected__doc__,
+"get_is_connected() -> bool\n\n"
+"Return true if this Server is still listening for new connections.\n");
+static PyObject *
+Server_get_is_connected (Server *self, PyObject *args UNUSED)
+{
+ dbus_bool_t ret;
+
+ TRACE(self);
+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
+ Py_BEGIN_ALLOW_THREADS
+ ret = dbus_server_get_is_connected(self->server);
+ Py_END_ALLOW_THREADS
+ return PyBool_FromLong(ret);
+}
+
+/* Server type object =============================================== */
+
+struct PyMethodDef DBusPyServer_tp_methods[] = {
+#define ENTRY(name, flags) {#name, (PyCFunction)Server_##name, flags, Server_##name##__doc__}
+ ENTRY(disconnect, METH_NOARGS),
+ ENTRY(get_address, METH_NOARGS),
+ ENTRY(get_id, METH_NOARGS),
+ ENTRY(get_is_connected, METH_NOARGS),
+ {NULL},
+#undef ENTRY
+};
+
+PyTypeObject DBusPyServer_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_dbus_bindings._Server",/*tp_name*/
+ sizeof(Server), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)Server_tp_dealloc,
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE,
+ Server_tp_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ offsetof(Server, weaklist), /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBusPyServer_tp_methods,/*tp_methods*/
+ 0, /*tp_members*/
+ 0, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ Server_tp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
+};
+
+dbus_bool_t
+dbus_py_init_server_types(void)
+{
+ /* Get a slot to store our weakref on DBus Server */
+ _server_python_slot = -1;
+ if (!dbus_server_allocate_data_slot(&_server_python_slot))
+ return FALSE;
+
+ if (PyType_Ready(&DBusPyServer_Type) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+dbus_bool_t
+dbus_py_insert_server_types(PyObject *this_module)
+{
+ if (PyModule_AddObject(this_module, "_Server",
+ (PyObject *)&DBusPyServer_Type) < 0) return FALSE;
+
+ return TRUE;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/signature.c b/_dbus_bindings/signature.c
new file mode 100644
index 0000000..6b31ab4
--- /dev/null
+++ b/_dbus_bindings/signature.c
@@ -0,0 +1,247 @@
+/* Implementation of Signature type for D-Bus bindings.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+#include "types-internal.h"
+
+PyDoc_STRVAR(Signature_tp_doc,
+"A string subclass whose values are restricted to valid D-Bus\n"
+"signatures. When iterated over, instead of individual characters it\n"
+"produces Signature instances representing single complete types.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" ``Signature(value: str or unicode[, variant_level: int]) -> Signature``\n"
+"\n"
+"``value`` must be a valid D-Bus signature (zero or more single complete\n"
+"types).\n"
+"\n"
+"``variant_level`` must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a signature, this is represented in Python by a\n"
+" Signature with variant_level==2.\n"
+);
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *string;
+ DBusSignatureIter iter;
+} SignatureIter;
+
+static void
+SignatureIter_tp_dealloc (SignatureIter *self)
+{
+ Py_XDECREF(self->string);
+ self->string = NULL;
+ PyObject_Del(self);
+}
+
+static PyObject *
+SignatureIter_tp_iternext (SignatureIter *self)
+{
+ char *sig;
+ PyObject *obj;
+
+ /* Stop immediately if finished or not correctly initialized */
+ if (!self->string) return NULL;
+
+ sig = dbus_signature_iter_get_signature(&(self->iter));
+ if (!sig) return PyErr_NoMemory();
+ obj = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "s", sig);
+ dbus_free(sig);
+ if (!obj) return NULL;
+
+ if (!dbus_signature_iter_next(&(self->iter))) {
+ /* mark object as having been finished with */
+ Py_DECREF(self->string);
+ self->string = NULL;
+ }
+
+ return obj;
+}
+
+static PyObject *
+SignatureIter_tp_iter(PyObject *self)
+{
+ Py_INCREF(self);
+ return self;
+}
+
+static PyTypeObject SignatureIterType = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "_dbus_bindings._SignatureIter",
+ sizeof(SignatureIter),
+ 0,
+ (destructor)SignatureIter_tp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ SignatureIter_tp_iter, /* tp_iter */
+ (iternextfunc)SignatureIter_tp_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ /* deliberately not callable! Use iter(Signature) instead */
+ 0, /* tp_new */
+ 0, /* tp_free */
+};
+
+static PyObject *
+Signature_tp_iter (PyObject *self)
+{
+ SignatureIter *iter = PyObject_New(SignatureIter, &SignatureIterType);
+ if (!iter) return NULL;
+
+ if (PyString_AS_STRING (self)[0]) {
+ Py_INCREF(self);
+ iter->string = self;
+ dbus_signature_iter_init(&(iter->iter), PyString_AS_STRING(self));
+ }
+ else {
+ /* this is a null string, make a null iterator */
+ iter->string = NULL;
+ }
+ return (PyObject *)iter;
+}
+
+static PyObject *
+Signature_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ const char *str = NULL;
+ PyObject *ignored;
+ static char *argnames[] = {"object_path", "variant_level", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:__new__", argnames,
+ &str, &ignored)) return NULL;
+ if (!dbus_signature_validate(str, NULL)) {
+ PyErr_SetString(PyExc_ValueError, "Corrupt type signature");
+ return NULL;
+ }
+ return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+}
+
+PyTypeObject DBusPySignature_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.Signature",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Signature_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ Signature_tp_iter, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPythonStringType), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Signature_tp_new, /* tp_new */
+ 0, /* tp_free */
+};
+
+dbus_bool_t
+dbus_py_init_signature(void)
+{
+ if (PyType_Ready(&SignatureIterType) < 0) return 0;
+
+ DBusPySignature_Type.tp_base = &DBusPyStrBase_Type;
+ if (PyType_Ready(&DBusPySignature_Type) < 0) return 0;
+ DBusPySignature_Type.tp_print = NULL;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_signature(PyObject *this_module)
+{
+ Py_INCREF(&DBusPySignature_Type);
+ if (PyModule_AddObject(this_module, "Signature",
+ (PyObject *)&DBusPySignature_Type) < 0) return 0;
+ Py_INCREF(&SignatureIterType);
+ if (PyModule_AddObject(this_module, "_SignatureIter",
+ (PyObject *)&SignatureIterType) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/string.c b/_dbus_bindings/string.c
new file mode 100644
index 0000000..19eab2c
--- /dev/null
+++ b/_dbus_bindings/string.c
@@ -0,0 +1,380 @@
+/* Simple D-Bus types: ObjectPath and other string types.
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "types-internal.h"
+#include <structmember.h>
+
+/* UTF-8 string representation ====================================== */
+
+PyDoc_STRVAR(UTF8String_tp_doc,
+"A string represented using UTF-8 - a subtype of `str`.\n"
+"\n"
+"All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
+"protocol\" they're transported as UTF-8.\n"
+"\n"
+"By default, when byte arrays are converted from D-Bus to Python, they\n"
+"come out as a `dbus.String`, which is a subtype of `unicode`.\n"
+"If you prefer to get UTF-8 strings (as instances of this class) or you\n"
+"want to avoid the conversion overhead of going from UTF-8 to Python's\n"
+"internal Unicode representation, you can pass the ``utf8_strings=True``\n"
+"keyword argument to any of these methods:\n"
+"\n"
+"* any D-Bus method proxy, or ``connect_to_signal``, on the objects returned\n"
+" by `Bus.get_object`\n"
+"* any D-Bus method on a `dbus.Interface`\n"
+"* `dbus.Interface.connect_to_signal`\n"
+"* `Bus.add_signal_receiver`\n"
+"\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.UTF8String(value: str or unicode[, variant_level: int]) -> UTF8String\n"
+"\n"
+"If value is a str object it must be valid UTF-8.\n"
+"\n"
+"variant_level must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a string, this is represented in Python by a\n"
+" String or UTF8String with variant_level==2.\n"
+":Since: 0.80 (in older versions, use dbus.String)\n"
+);
+
+static PyObject *
+UTF8String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ const char *str = NULL;
+ long variantness = 0;
+ static char *argnames[] = {"value", "variant_level", NULL};
+ PyObject *unicode;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
+ &str, &variantness)) return NULL;
+ unicode = PyUnicode_DecodeUTF8(str, strlen(str), NULL);
+ if (!unicode) return NULL;
+ Py_DECREF(unicode);
+ return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+}
+
+PyTypeObject DBusPyUTF8String_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.UTF8String",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UTF8String_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyStrBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ UTF8String_tp_new, /* tp_new */
+};
+
+/* Object path ====================================================== */
+
+PyDoc_STRVAR(ObjectPath_tp_doc,
+"A D-Bus object path, such as '/com/example/MyApp/Documents/abc'.\n"
+"\n"
+"ObjectPath is a subtype of str, and object-paths behave like strings.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" dbus.ObjectPath(path: str, variant_level: int) -> ObjectPath\n"
+"\n"
+"path must be an ASCII string following the syntax of object paths.\n"
+"variant_level must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing an object path, this is represented in Python by an\n"
+" ObjectPath with variant_level==2.\n"
+);
+
+static PyObject *
+ObjectPath_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ const char *str = NULL;
+ long variantness = 0;
+ static char *argnames[] = {"object_path", "variant_level", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
+ &str, &variantness)) return NULL;
+ if (!dbus_py_validate_object_path(str)) {
+ return NULL;
+ }
+ return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+}
+
+PyTypeObject DBusPyObjectPath_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.ObjectPath",
+ 0,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ObjectPath_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&DBusPyStrBase_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ ObjectPath_tp_new, /* tp_new */
+};
+
+/* Unicode string representation ==================================== */
+
+PyDoc_STRVAR(String_tp_doc,
+"A string represented using Unicode - a subtype of `unicode`.\n"
+"\n"
+"All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
+"protocol\" they're transported as UTF-8.\n"
+"\n"
+"By default, when strings are converted from D-Bus to Python, they\n"
+"come out as this class. If you prefer to get UTF-8 strings (as instances\n"
+"of a subtype of `str`) or you want to avoid the conversion overhead of\n"
+"going from UTF-8 to Python's internal Unicode representation, see the\n"
+"documentation for `dbus.UTF8String`.\n"
+"\n"
+"Constructor::\n"
+"\n"
+" String(value: str or unicode[, variant_level: int]) -> String\n"
+"\n"
+"variant_level must be non-negative; the default is 0.\n"
+"\n"
+":IVariables:\n"
+" `variant_level` : int\n"
+" Indicates how many nested Variant containers this object\n"
+" is contained in: if a message's wire format has a variant containing a\n"
+" variant containing a string, this is represented in Python by a\n"
+" String or UTF8String with variant_level==2.\n"
+);
+
+static PyMemberDef String_tp_members[] = {
+ {"variant_level", T_LONG, offsetof(DBusPyString, variant_level),
+ READONLY,
+ "The number of nested variants wrapping the real data. "
+ "0 if not in a variant"},
+ {NULL},
+};
+
+static PyObject *
+String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+{
+ PyObject *self;
+ long variantness = 0;
+ static char *argnames[] = {"variant_level", NULL};
+
+ if (PyTuple_Size(args) > 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "__new__ takes at most one positional parameter");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
+ "|l:__new__", argnames,
+ &variantness)) return NULL;
+ if (variantness < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "variant_level must be non-negative");
+ return NULL;
+ }
+ self = (PyUnicode_Type.tp_new)(cls, args, NULL);
+ if (self) {
+ ((DBusPyString *)self)->variant_level = variantness;
+ }
+ return self;
+}
+
+static PyObject *
+String_tp_repr(PyObject *self)
+{
+ PyObject *parent_repr = (PyUnicode_Type.tp_repr)(self);
+ PyObject *my_repr;
+
+ if (!parent_repr) {
+ return NULL;
+ }
+ if (((DBusPyString *)self)->variant_level > 0) {
+ my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
+ self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr),
+ ((DBusPyString *)self)->variant_level);
+ }
+ else {
+ my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
+ PyString_AS_STRING(parent_repr));
+ }
+ /* whether my_repr is NULL or not: */
+ Py_DECREF(parent_repr);
+ return my_repr;
+}
+
+PyTypeObject DBusPyString_Type = {
+ PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
+ 0,
+ "dbus.String",
+ sizeof(DBusPyString),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ String_tp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ dbus_py_immutable_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ String_tp_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ String_tp_members, /* tp_members */
+ 0, /* tp_getset */
+ DEFERRED_ADDRESS(&PyUnicode_Type), /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ String_tp_new, /* tp_new */
+};
+
+dbus_bool_t
+dbus_py_init_string_types(void)
+{
+ /* don't need to do strange contortions for unicode, since it's not a
+ * "variable-size" object (it has a pointer to its data instead)
+ */
+ if (PyUnicode_Type.tp_itemsize != 0) {
+ fprintf(stderr, "dbus-python is not compatible with this version of "
+ "Python (unicode objects are assumed to be fixed-size)");
+ return 0;
+ }
+ DBusPyString_Type.tp_base = &PyUnicode_Type;
+ if (PyType_Ready(&DBusPyString_Type) < 0) return 0;
+ DBusPyString_Type.tp_print = NULL;
+
+ DBusPyUTF8String_Type.tp_base = &DBusPyStrBase_Type;
+ if (PyType_Ready(&DBusPyUTF8String_Type) < 0) return 0;
+ DBusPyUTF8String_Type.tp_print = NULL;
+
+ DBusPyObjectPath_Type.tp_base = &DBusPyStrBase_Type;
+ if (PyType_Ready(&DBusPyObjectPath_Type) < 0) return 0;
+ DBusPyObjectPath_Type.tp_print = NULL;
+
+ DBusPyBoolean_Type.tp_base = &DBusPyIntBase_Type;
+ if (PyType_Ready(&DBusPyBoolean_Type) < 0) return 0;
+ DBusPyBoolean_Type.tp_print = NULL;
+
+ return 1;
+}
+
+dbus_bool_t
+dbus_py_insert_string_types(PyObject *this_module)
+{
+ Py_INCREF(&DBusPyObjectPath_Type);
+ Py_INCREF(&DBusPyUTF8String_Type);
+ Py_INCREF(&DBusPyString_Type);
+ if (PyModule_AddObject(this_module, "ObjectPath",
+ (PyObject *)&DBusPyObjectPath_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "UTF8String",
+ (PyObject *)&DBusPyUTF8String_Type) < 0) return 0;
+ if (PyModule_AddObject(this_module, "String",
+ (PyObject *)&DBusPyString_Type) < 0) return 0;
+
+ return 1;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/_dbus_bindings/types-internal.h b/_dbus_bindings/types-internal.h
new file mode 100644
index 0000000..a5c8147
--- /dev/null
+++ b/_dbus_bindings/types-internal.h
@@ -0,0 +1,95 @@
+/* D-Bus types: implementation internals
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include <stdint.h>
+
+#include "dbus_bindings-internal.h"
+
+#ifndef DBUS_BINDINGS_TYPES_INTERNAL_H
+#define DBUS_BINDINGS_TYPES_INTERNAL_H
+
+extern PyTypeObject DBusPyIntBase_Type;
+DEFINE_CHECK(DBusPyIntBase)
+
+typedef struct {
+ PyIntObject base;
+ long variant_level;
+} DBusPyIntBase;
+
+extern PyTypeObject DBusPyLongBase_Type;
+DEFINE_CHECK(DBusPyLongBase)
+
+extern PyTypeObject DBusPyFloatBase_Type;
+DEFINE_CHECK(DBusPyFloatBase)
+
+typedef struct {
+ PyFloatObject base;
+ long variant_level;
+} DBusPyFloatBase;
+
+typedef struct {
+ PyUnicodeObject unicode;
+ long variant_level;
+} DBusPyString;
+
+extern PyTypeObject DBusPyStrBase_Type;
+DEFINE_CHECK(DBusPyStrBase)
+
+dbus_int16_t dbus_py_int16_range_check(PyObject *);
+dbus_uint16_t dbus_py_uint16_range_check(PyObject *);
+dbus_int32_t dbus_py_int32_range_check(PyObject *);
+dbus_uint32_t dbus_py_uint32_range_check(PyObject *);
+
+#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
+# define DBUS_PYTHON_64_BIT_WORKS 1
+dbus_int64_t dbus_py_int64_range_check(PyObject *);
+dbus_uint64_t dbus_py_uint64_range_check(PyObject *);
+#else
+# undef DBUS_PYTHON_64_BIT_WORKS
+#endif /* defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG) */
+
+extern PyObject *dbus_py_variant_level_const;
+extern PyObject *dbus_py_signature_const;
+extern PyObject *dbus_py__dbus_object_path__const;
+
+typedef struct {
+ PyListObject super;
+ PyObject *signature;
+ long variant_level;
+} DBusPyArray;
+
+typedef struct {
+ PyDictObject super;
+ PyObject *signature;
+ long variant_level;
+} DBusPyDict;
+
+PyObject *dbus_py_variant_level_getattro(PyObject *obj, PyObject *name);
+dbus_bool_t dbus_py_variant_level_set(PyObject *obj, long variant_level);
+void dbus_py_variant_level_clear(PyObject *obj);
+long dbus_py_variant_level_get(PyObject *obj);
+
+#endif
diff --git a/_dbus_bindings/validation.c b/_dbus_bindings/validation.c
new file mode 100644
index 0000000..abec0a9
--- /dev/null
+++ b/_dbus_bindings/validation.c
@@ -0,0 +1,245 @@
+/* Implementation of various validation functions for use in dbus-python.
+ *
+ * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbus_bindings-internal.h"
+
+dbus_bool_t
+dbus_py_validate_bus_name(const char *name,
+ dbus_bool_t may_be_unique,
+ dbus_bool_t may_be_not_unique)
+{
+ dbus_bool_t dot = FALSE;
+ dbus_bool_t unique;
+ char last;
+ const char *ptr;
+
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Invalid bus name: "
+ "may not be empty");
+ return FALSE;
+ }
+ unique = (name[0] == ':');
+ if (unique && !may_be_unique) {
+ PyErr_Format(PyExc_ValueError, "Invalid well-known bus name '%s':"
+ "only unique names may start with ':'", name);
+ return FALSE;
+ }
+ if (!unique && !may_be_not_unique) {
+ PyErr_Format(PyExc_ValueError, "Invalid unique bus name '%s': "
+ "unique names must start with ':'", name);
+ return FALSE;
+ }
+ if (strlen(name) > 255) {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "too long (> 255 characters)", name);
+ return FALSE;
+ }
+ last = '\0';
+ for (ptr = name + (unique ? 1 : 0); *ptr; ptr++) {
+ if (*ptr == '.') {
+ dot = TRUE;
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "contains substring '..'", name);
+ return FALSE;
+ }
+ else if (last == '\0') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "must not start with '.'", name);
+ return FALSE;
+ }
+ }
+ else if (*ptr >= '0' && *ptr <= '9') {
+ if (!unique) {
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "a digit may not follow '.' except in a "
+ "unique name starting with ':'", name);
+ return FALSE;
+ }
+ else if (last == '\0') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "must not start with a digit", name);
+ return FALSE;
+ }
+ }
+ }
+ else if ((*ptr < 'a' || *ptr > 'z') &&
+ (*ptr < 'A' || *ptr > 'Z') && *ptr != '_' && *ptr != '-') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
+ "contains invalid character '%c'", name, *ptr);
+ return FALSE;
+ }
+ last = *ptr;
+ }
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
+ "not end with '.'", name);
+ return FALSE;
+ }
+ if (!dot) {
+ PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
+ "contain '.'", name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+dbus_bool_t
+dbus_py_validate_member_name(const char *name)
+{
+ const char *ptr;
+
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Invalid member name: may not "
+ "be empty");
+ return FALSE;
+ }
+ if (strlen(name) > 255) {
+ PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
+ "too long (> 255 characters)", name);
+ return FALSE;
+ }
+ for (ptr = name; *ptr; ptr++) {
+ if (*ptr >= '0' && *ptr <= '9') {
+ if (ptr == name) {
+ PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
+ "must not start with a digit", name);
+ return FALSE;
+ }
+ }
+ else if ((*ptr < 'a' || *ptr > 'z') &&
+ (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
+ PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
+ "contains invalid character '%c'", name, *ptr);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+dbus_bool_t
+dbus_py_validate_interface_name(const char *name)
+{
+ dbus_bool_t dot = FALSE;
+ char last;
+ const char *ptr;
+
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Invalid interface or error name: "
+ "may not be empty");
+ return FALSE;
+ }
+ if (strlen(name) > 255) {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
+ "too long (> 255 characters)", name);
+ return FALSE;
+ }
+ last = '\0';
+ for (ptr = name; *ptr; ptr++) {
+ if (*ptr == '.') {
+ dot = TRUE;
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or "
+ "error name '%s': contains substring '..'", name);
+ return FALSE;
+ }
+ else if (last == '\0') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error "
+ "name '%s': must not start with '.'", name);
+ return FALSE;
+ }
+ }
+ else if (*ptr >= '0' && *ptr <= '9') {
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error "
+ "name '%s': a digit may not follow '.'", name);
+ return FALSE;
+ }
+ else if (last == '\0') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error "
+ "name '%s': must not start with a digit", name);
+ return FALSE;
+ }
+ }
+ else if ((*ptr < 'a' || *ptr > 'z') &&
+ (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error "
+ "name '%s': contains invalid character '%c'",
+ name, *ptr);
+ return FALSE;
+ }
+ last = *ptr;
+ }
+ if (last == '.') {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error name "
+ "'%s': must not end with '.'", name);
+ return FALSE;
+ }
+ if (!dot) {
+ PyErr_Format(PyExc_ValueError, "Invalid interface or error name "
+ "'%s': must contain '.'", name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+dbus_bool_t
+dbus_py_validate_object_path(const char *path)
+{
+ const char *ptr;
+
+ if (path[0] != '/') {
+ PyErr_Format(PyExc_ValueError, "Invalid object path '%s': does not "
+ "start with '/'", path);
+ return FALSE;
+ }
+ if (path[1] == '\0') return TRUE;
+ for (ptr = path + 1; *ptr; ptr++) {
+ if (*ptr == '/') {
+ if (ptr[-1] == '/') {
+ PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
+ "contains substring '//'", path);
+ return FALSE;
+ }
+ }
+ else if ((*ptr < 'a' || *ptr > 'z') &&
+ (*ptr < 'A' || *ptr > 'Z') &&
+ (*ptr < '0' || *ptr > '9') && *ptr != '_') {
+ PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
+ "contains invalid character '%c'", path, *ptr);
+ return FALSE;
+ }
+ }
+ if (ptr[-1] == '/') {
+ PyErr_Format(PyExc_ValueError, "Invalid object path '%s': ends "
+ "with '/' and is not just '/'", path);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */