diff options
Diffstat (limited to 'glib')
-rw-r--r-- | glib/Makefile.am | 59 | ||||
-rw-r--r-- | glib/Makefile.in | 787 | ||||
-rw-r--r-- | glib/__init__.py | 25 | ||||
-rw-r--r-- | glib/glibmodule.c | 896 | ||||
-rw-r--r-- | glib/option.py | 350 | ||||
-rw-r--r-- | glib/pygiochannel.c | 740 | ||||
-rw-r--r-- | glib/pygiochannel.h | 29 | ||||
-rw-r--r-- | glib/pyglib-private.h | 46 | ||||
-rw-r--r-- | glib/pyglib-python-compat.h | 120 | ||||
-rw-r--r-- | glib/pyglib.c | 577 | ||||
-rw-r--r-- | glib/pyglib.h | 94 | ||||
-rw-r--r-- | glib/pygmaincontext.c | 99 | ||||
-rw-r--r-- | glib/pygmaincontext.h | 40 | ||||
-rw-r--r-- | glib/pygmainloop.c | 354 | ||||
-rw-r--r-- | glib/pygmainloop.h | 36 | ||||
-rw-r--r-- | glib/pygoptioncontext.c | 312 | ||||
-rw-r--r-- | glib/pygoptioncontext.h | 37 | ||||
-rw-r--r-- | glib/pygoptiongroup.c | 270 | ||||
-rw-r--r-- | glib/pygoptiongroup.h | 40 | ||||
-rw-r--r-- | glib/pygsource.c | 723 | ||||
-rw-r--r-- | glib/pygsource.h | 39 | ||||
-rw-r--r-- | glib/pygspawn.c | 263 | ||||
-rw-r--r-- | glib/pygspawn.h | 32 |
23 files changed, 5968 insertions, 0 deletions
diff --git a/glib/Makefile.am b/glib/Makefile.am new file mode 100644 index 0000000..d230da4 --- /dev/null +++ b/glib/Makefile.am @@ -0,0 +1,59 @@ +AUTOMAKE_OPTIONS = 1.7 +INCLUDES = $(PYTHON_INCLUDES) $(GLIB_CFLAGS) -DPY_SSIZE_T_CLEAN + +pkgincludedir = $(includedir)/pygtk-2.0 +pkginclude_HEADERS = pyglib.h + +lib_LTLIBRARIES = libpyglib-2.0-@PYTHON_BASENAME@.la + +pkgpyexecdir = $(pyexecdir)/gtk-2.0 + +pyglibdir = $(pkgpyexecdir)/glib +pyglib_PYTHON = \ + __init__.py \ + option.py +pyglib_LTLIBRARIES = _glib.la + +common_ldflags = -module -avoid-version +if PLATFORM_WIN32 +common_ldflags += -no-undefined +endif + +libpyglib_2_0_@PYTHON_BASENAME@_la_CFLAGS = $(GLIB_CFLAGS) +libpyglib_2_0_@PYTHON_BASENAME@_la_LIBADD = $(GLIB_LIBS) $(FFI_LIBS) +libpyglib_2_0_@PYTHON_BASENAME@_la_SOURCES = \ + pyglib.c \ + pyglib.h \ + pyglib-private.h \ + pyglib-python-compat.h + +_glib_la_CFLAGS = $(GLIB_CFLAGS) +_glib_la_LDFLAGS = $(common_ldflags) -export-symbols-regex "_glib|PyInit__glib" +_glib_la_LIBADD = $(GLIB_LIBS) libpyglib-2.0-@PYTHON_BASENAME@.la +_glib_la_SOURCES = \ + glibmodule.c \ + pygiochannel.c \ + pygiochannel.h \ + pygoptioncontext.c \ + pygoptioncontext.h \ + pygoptiongroup.c \ + pygoptiongroup.h \ + pygmaincontext.c \ + pygmaincontext.h \ + pygmainloop.c \ + pygmainloop.h \ + pygsource.c \ + pygsource.h \ + pygspawn.c \ + pygspawn.h + +if PLATFORM_WIN32 +_glib_la_CFLAGS += -DPLATFORM_WIN32 +endif + + +all: $(pyglib_LTLIBRARIES:.la=.so) +clean-local: + rm -f $(pyglib_LTLIBRARIES:.la=.so) +.la.so: + $(LN_S) .libs/$@ $@ || true diff --git a/glib/Makefile.in b/glib/Makefile.in new file mode 100644 index 0000000..634bdce --- /dev/null +++ b/glib/Makefile.in @@ -0,0 +1,787 @@ +# 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@ +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@ +@PLATFORM_WIN32_TRUE@am__append_1 = -no-undefined +@PLATFORM_WIN32_TRUE@am__append_2 = -DPLATFORM_WIN32 +subdir = glib +DIST_COMMON = $(pkginclude_HEADERS) $(pyglib_PYTHON) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_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)$(libdir)" "$(DESTDIR)$(pyglibdir)" \ + "$(DESTDIR)$(pyglibdir)" "$(DESTDIR)$(pkgincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(pyglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +_glib_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + libpyglib-2.0-@PYTHON_BASENAME@.la +am__glib_la_OBJECTS = _glib_la-glibmodule.lo _glib_la-pygiochannel.lo \ + _glib_la-pygoptioncontext.lo _glib_la-pygoptiongroup.lo \ + _glib_la-pygmaincontext.lo _glib_la-pygmainloop.lo \ + _glib_la-pygsource.lo _glib_la-pygspawn.lo +_glib_la_OBJECTS = $(am__glib_la_OBJECTS) +_glib_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(_glib_la_CFLAGS) $(CFLAGS) \ + $(_glib_la_LDFLAGS) $(LDFLAGS) -o $@ +libpyglib_2_0_@PYTHON_BASENAME@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libpyglib_2_0_@PYTHON_BASENAME@_la_OBJECTS = \ + libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo +libpyglib_2_0_@PYTHON_BASENAME@_la_OBJECTS = \ + $(am_libpyglib_2_0_@PYTHON_BASENAME@_la_OBJECTS) +libpyglib_2_0_@PYTHON_BASENAME@_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libpyglib_2_0_@PYTHON_BASENAME@_la_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(_glib_la_SOURCES) \ + $(libpyglib_2_0_@PYTHON_BASENAME@_la_SOURCES) +DIST_SOURCES = $(_glib_la_SOURCES) \ + $(libpyglib_2_0_@PYTHON_BASENAME@_la_SOURCES) +py_compile = $(top_srcdir)/py-compile +HEADERS = $(pkginclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkgincludedir = $(includedir)/pygtk-2.0 +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FFI_CFLAGS = @FFI_CFLAGS@ +FFI_LIBS = @FFI_LIBS@ +FGREP = @FGREP@ +GIOUNIX_CFLAGS = @GIOUNIX_CFLAGS@ +GIOUNIX_LIBS = @GIOUNIX_LIBS@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +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@ +LIBFFI_PC = @LIBFFI_PC@ +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_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLATFORM = @PLATFORM@ +PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@ +PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@ +PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@ +PYTHON = @PYTHON@ +PYTHON_BASENAME = @PYTHON_BASENAME@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +THREADING_CFLAGS = @THREADING_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +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 = $(pyexecdir)/gtk-2.0 +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pygobject_CODEGEN_DEFINES = @pygobject_CODEGEN_DEFINES@ +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@ +AUTOMAKE_OPTIONS = 1.7 +INCLUDES = $(PYTHON_INCLUDES) $(GLIB_CFLAGS) -DPY_SSIZE_T_CLEAN +pkginclude_HEADERS = pyglib.h +lib_LTLIBRARIES = libpyglib-2.0-@PYTHON_BASENAME@.la +pyglibdir = $(pkgpyexecdir)/glib +pyglib_PYTHON = \ + __init__.py \ + option.py + +pyglib_LTLIBRARIES = _glib.la +common_ldflags = -module -avoid-version $(am__append_1) +libpyglib_2_0_@PYTHON_BASENAME@_la_CFLAGS = $(GLIB_CFLAGS) +libpyglib_2_0_@PYTHON_BASENAME@_la_LIBADD = $(GLIB_LIBS) $(FFI_LIBS) +libpyglib_2_0_@PYTHON_BASENAME@_la_SOURCES = \ + pyglib.c \ + pyglib.h \ + pyglib-private.h \ + pyglib-python-compat.h + +_glib_la_CFLAGS = $(GLIB_CFLAGS) $(am__append_2) +_glib_la_LDFLAGS = $(common_ldflags) -export-symbols-regex "_glib|PyInit__glib" +_glib_la_LIBADD = $(GLIB_LIBS) libpyglib-2.0-@PYTHON_BASENAME@.la +_glib_la_SOURCES = \ + glibmodule.c \ + pygiochannel.c \ + pygiochannel.h \ + pygoptioncontext.c \ + pygoptioncontext.h \ + pygoptiongroup.c \ + pygoptiongroup.h \ + pygmaincontext.c \ + pygmaincontext.h \ + pygmainloop.c \ + pygmainloop.h \ + pygsource.c \ + pygsource.h \ + pygspawn.c \ + pygspawn.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .la .lo .o .obj .so +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu glib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu glib/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-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || 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)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_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 +install-pyglibLTLIBRARIES: $(pyglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pyglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pyglibdir)" + @list='$(pyglib_LTLIBRARIES)'; test -n "$(pyglibdir)" || 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)$(pyglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyglibdir)"; \ + } + +uninstall-pyglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pyglib_LTLIBRARIES)'; test -n "$(pyglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyglibdir)/$$f"; \ + done + +clean-pyglibLTLIBRARIES: + -test -z "$(pyglib_LTLIBRARIES)" || rm -f $(pyglib_LTLIBRARIES) + @list='$(pyglib_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 +_glib.la: $(_glib_la_OBJECTS) $(_glib_la_DEPENDENCIES) + $(_glib_la_LINK) -rpath $(pyglibdir) $(_glib_la_OBJECTS) $(_glib_la_LIBADD) $(LIBS) +libpyglib-2.0-@PYTHON_BASENAME@.la: $(libpyglib_2_0_@PYTHON_BASENAME@_la_OBJECTS) $(libpyglib_2_0_@PYTHON_BASENAME@_la_DEPENDENCIES) + $(libpyglib_2_0_@PYTHON_BASENAME@_la_LINK) -rpath $(libdir) $(libpyglib_2_0_@PYTHON_BASENAME@_la_OBJECTS) $(libpyglib_2_0_@PYTHON_BASENAME@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-glibmodule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygiochannel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygmaincontext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygmainloop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygoptioncontext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygoptiongroup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygsource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygspawn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@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@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@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@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@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 $@ $< + +_glib_la-glibmodule.lo: glibmodule.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-glibmodule.lo -MD -MP -MF $(DEPDIR)/_glib_la-glibmodule.Tpo -c -o _glib_la-glibmodule.lo `test -f 'glibmodule.c' || echo '$(srcdir)/'`glibmodule.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-glibmodule.Tpo $(DEPDIR)/_glib_la-glibmodule.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glibmodule.c' object='_glib_la-glibmodule.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-glibmodule.lo `test -f 'glibmodule.c' || echo '$(srcdir)/'`glibmodule.c + +_glib_la-pygiochannel.lo: pygiochannel.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygiochannel.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygiochannel.Tpo -c -o _glib_la-pygiochannel.lo `test -f 'pygiochannel.c' || echo '$(srcdir)/'`pygiochannel.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygiochannel.Tpo $(DEPDIR)/_glib_la-pygiochannel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygiochannel.c' object='_glib_la-pygiochannel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygiochannel.lo `test -f 'pygiochannel.c' || echo '$(srcdir)/'`pygiochannel.c + +_glib_la-pygoptioncontext.lo: pygoptioncontext.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygoptioncontext.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygoptioncontext.Tpo -c -o _glib_la-pygoptioncontext.lo `test -f 'pygoptioncontext.c' || echo '$(srcdir)/'`pygoptioncontext.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygoptioncontext.Tpo $(DEPDIR)/_glib_la-pygoptioncontext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygoptioncontext.c' object='_glib_la-pygoptioncontext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygoptioncontext.lo `test -f 'pygoptioncontext.c' || echo '$(srcdir)/'`pygoptioncontext.c + +_glib_la-pygoptiongroup.lo: pygoptiongroup.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygoptiongroup.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygoptiongroup.Tpo -c -o _glib_la-pygoptiongroup.lo `test -f 'pygoptiongroup.c' || echo '$(srcdir)/'`pygoptiongroup.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygoptiongroup.Tpo $(DEPDIR)/_glib_la-pygoptiongroup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygoptiongroup.c' object='_glib_la-pygoptiongroup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygoptiongroup.lo `test -f 'pygoptiongroup.c' || echo '$(srcdir)/'`pygoptiongroup.c + +_glib_la-pygmaincontext.lo: pygmaincontext.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygmaincontext.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygmaincontext.Tpo -c -o _glib_la-pygmaincontext.lo `test -f 'pygmaincontext.c' || echo '$(srcdir)/'`pygmaincontext.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygmaincontext.Tpo $(DEPDIR)/_glib_la-pygmaincontext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygmaincontext.c' object='_glib_la-pygmaincontext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygmaincontext.lo `test -f 'pygmaincontext.c' || echo '$(srcdir)/'`pygmaincontext.c + +_glib_la-pygmainloop.lo: pygmainloop.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygmainloop.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygmainloop.Tpo -c -o _glib_la-pygmainloop.lo `test -f 'pygmainloop.c' || echo '$(srcdir)/'`pygmainloop.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygmainloop.Tpo $(DEPDIR)/_glib_la-pygmainloop.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygmainloop.c' object='_glib_la-pygmainloop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygmainloop.lo `test -f 'pygmainloop.c' || echo '$(srcdir)/'`pygmainloop.c + +_glib_la-pygsource.lo: pygsource.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygsource.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygsource.Tpo -c -o _glib_la-pygsource.lo `test -f 'pygsource.c' || echo '$(srcdir)/'`pygsource.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygsource.Tpo $(DEPDIR)/_glib_la-pygsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygsource.c' object='_glib_la-pygsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygsource.lo `test -f 'pygsource.c' || echo '$(srcdir)/'`pygsource.c + +_glib_la-pygspawn.lo: pygspawn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygspawn.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygspawn.Tpo -c -o _glib_la-pygspawn.lo `test -f 'pygspawn.c' || echo '$(srcdir)/'`pygspawn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/_glib_la-pygspawn.Tpo $(DEPDIR)/_glib_la-pygspawn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygspawn.c' object='_glib_la-pygspawn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygspawn.lo `test -f 'pygspawn.c' || echo '$(srcdir)/'`pygspawn.c + +libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo: pyglib.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpyglib_2_0_@PYTHON_BASENAME@_la_CFLAGS) $(CFLAGS) -MT libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo -MD -MP -MF $(DEPDIR)/libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.Tpo -c -o libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo `test -f 'pyglib.c' || echo '$(srcdir)/'`pyglib.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.Tpo $(DEPDIR)/libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pyglib.c' object='libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpyglib_2_0_@PYTHON_BASENAME@_la_CFLAGS) $(CFLAGS) -c -o libpyglib_2_0_@PYTHON_BASENAME@_la-pyglib.lo `test -f 'pyglib.c' || echo '$(srcdir)/'`pyglib.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pyglibPYTHON: $(pyglib_PYTHON) + @$(NORMAL_INSTALL) + test -z "$(pyglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pyglibdir)" + @list='$(pyglib_PYTHON)'; dlist=; list2=; test -n "$(pyglibdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ + if test -f $$b$$p; then \ + $(am__strip_dir) \ + dlist="$$dlist $$f"; \ + list2="$$list2 $$b$$p"; \ + else :; fi; \ + done; \ + for file in $$list2; do echo $$file; done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pyglibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pyglibdir)" || exit $$?; \ + done || exit $$?; \ + if test -n "$$dlist"; then \ + if test -z "$(DESTDIR)"; then \ + PYTHON=$(PYTHON) $(py_compile) --basedir "$(pyglibdir)" $$dlist; \ + else \ + PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(pyglibdir)" $$dlist; \ + fi; \ + else :; fi + +uninstall-pyglibPYTHON: + @$(NORMAL_UNINSTALL) + @list='$(pyglib_PYTHON)'; test -n "$(pyglibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + filesc=`echo "$$files" | sed 's|$$|c|'`; \ + fileso=`echo "$$files" | sed 's|$$|o|'`; \ + echo " ( cd '$(DESTDIR)$(pyglibdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pyglibdir)" && rm -f $$files || exit $$?; \ + echo " ( cd '$(DESTDIR)$(pyglibdir)' && rm -f" $$filesc ")"; \ + cd "$(DESTDIR)$(pyglibdir)" && rm -f $$filesc || exit $$?; \ + echo " ( cd '$(DESTDIR)$(pyglibdir)' && rm -f" $$fileso ")"; \ + cd "$(DESTDIR)$(pyglibdir)" && rm -f $$fileso +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files + +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 +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pyglibdir)" "$(DESTDIR)$(pyglibdir)" "$(DESTDIR)$(pkgincludedir)"; 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-libLTLIBRARIES clean-libtool clean-local \ + clean-pyglibLTLIBRARIES 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-pkgincludeHEADERS install-pyglibLTLIBRARIES \ + install-pyglibPYTHON + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +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-libLTLIBRARIES uninstall-pkgincludeHEADERS \ + uninstall-pyglibLTLIBRARIES uninstall-pyglibPYTHON + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-local \ + clean-pyglibLTLIBRARIES 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-libLTLIBRARIES \ + install-man install-pdf install-pdf-am \ + install-pkgincludeHEADERS install-ps install-ps-am \ + install-pyglibLTLIBRARIES install-pyglibPYTHON 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-libLTLIBRARIES \ + uninstall-pkgincludeHEADERS uninstall-pyglibLTLIBRARIES \ + uninstall-pyglibPYTHON + + +all: $(pyglib_LTLIBRARIES:.la=.so) +clean-local: + rm -f $(pyglib_LTLIBRARIES:.la=.so) +.la.so: + $(LN_S) .libs/$@ $@ || true + +# 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/glib/__init__.py b/glib/__init__.py new file mode 100644 index 0000000..b114cb9 --- /dev/null +++ b/glib/__init__.py @@ -0,0 +1,25 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# pygobject - Python bindings for the GObject library +# Copyright (C) 2006-2008 Johan Dahlin +# +# glib/__init__.py: initialisation file for glib module +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA + +from glib._glib import * +_PyGLib_API = _glib._PyGLib_API + +del _glib diff --git a/glib/glibmodule.c b/glib/glibmodule.c new file mode 100644 index 0000000..f794d5d --- /dev/null +++ b/glib/glibmodule.c @@ -0,0 +1,896 @@ +/* -*- Mode: C; c-set-style: python; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * glibmodule.c: wrapper for the glib library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <Python.h> +#include <glib.h> +#include "pyglib.h" +#include "pyglib-private.h" +#include "pygiochannel.h" +#include "pygmaincontext.h" +#include "pygmainloop.h" +#include "pygoptioncontext.h" +#include "pygoptiongroup.h" +#include "pygsource.h" +#include "pygspawn.h" + +#define PYGLIB_MAJOR_VERSION PYGOBJECT_MAJOR_VERSION +#define PYGLIB_MINOR_VERSION PYGOBJECT_MINOR_VERSION +#define PYGLIB_MICRO_VERSION PYGOBJECT_MICRO_VERSION + + +/* ---------------- glib module functions -------------------- */ + +struct _PyGChildData { + PyObject *func; + PyObject *data; +}; + +static gint +get_handler_priority(gint *priority, PyObject *kwargs) +{ + Py_ssize_t len, pos; + PyObject *key, *val; + + /* no keyword args? leave as default */ + if (kwargs == NULL) return 0; + + len = PyDict_Size(kwargs); + if (len == 0) return 0; + + if (len != 1) { + PyErr_SetString(PyExc_TypeError, + "expecting at most one keyword argument"); + return -1; + } + pos = 0; + PyDict_Next(kwargs, &pos, &key, &val); + if (!_PyUnicode_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "keyword argument name is not a string"); + return -1; + } + + if (strcmp(_PyUnicode_AsString(key), "priority") != 0) { + PyErr_SetString(PyExc_TypeError, + "only 'priority' keyword argument accepted"); + return -1; + } + + *priority = _PyLong_AsLong(val); + if (PyErr_Occurred()) { + PyErr_Clear(); + PyErr_SetString(PyExc_ValueError, "could not get priority value"); + return -1; + } + return 0; +} + +static PyObject * +pyglib_threads_init(PyObject *unused, PyObject *args, PyObject *kwargs) +{ + if (!pyglib_enable_threads()) + return NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyglib_idle_add(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *first, *callback, *cbargs = NULL, *data; + gint len, priority = G_PRIORITY_DEFAULT_IDLE; + guint handler_id; + + len = PyTuple_Size(args); + if (len < 1) { + PyErr_SetString(PyExc_TypeError, + "idle_add requires at least 1 argument"); + return NULL; + } + first = PySequence_GetSlice(args, 0, 1); + if (!PyArg_ParseTuple(first, "O:idle_add", &callback)) { + Py_DECREF(first); + return NULL; + } + Py_DECREF(first); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "first argument not callable"); + return NULL; + } + if (get_handler_priority(&priority, kwargs) < 0) + return NULL; + + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + handler_id = g_idle_add_full(priority, + _pyglib_handler_marshal, data, + _pyglib_destroy_notify); + return _PyLong_FromLong(handler_id); +} + + +static PyObject * +pyglib_timeout_add(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *first, *callback, *cbargs = NULL, *data; + gint len, priority = G_PRIORITY_DEFAULT; + guint interval, handler_id; + + len = PyTuple_Size(args); + if (len < 2) { + PyErr_SetString(PyExc_TypeError, + "timeout_add requires at least 2 args"); + return NULL; + } + first = PySequence_GetSlice(args, 0, 2); + if (!PyArg_ParseTuple(first, "IO:timeout_add", &interval, &callback)) { + Py_DECREF(first); + return NULL; + } + Py_DECREF(first); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "second argument not callable"); + return NULL; + } + if (get_handler_priority(&priority, kwargs) < 0) + return NULL; + + cbargs = PySequence_GetSlice(args, 2, len); + if (cbargs == NULL) + return NULL; + + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + handler_id = g_timeout_add_full(priority, interval, + _pyglib_handler_marshal, data, + _pyglib_destroy_notify); + return _PyLong_FromLong(handler_id); +} + +static PyObject * +pyglib_timeout_add_seconds(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *first, *callback, *cbargs = NULL, *data; + gint len, priority = G_PRIORITY_DEFAULT; + guint interval, handler_id; + + len = PyTuple_Size(args); + if (len < 2) { + PyErr_SetString(PyExc_TypeError, + "timeout_add_seconds requires at least 2 args"); + return NULL; + } + first = PySequence_GetSlice(args, 0, 2); + if (!PyArg_ParseTuple(first, "IO:timeout_add_seconds", &interval, &callback)) { + Py_DECREF(first); + return NULL; + } + Py_DECREF(first); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "second argument not callable"); + return NULL; + } + if (get_handler_priority(&priority, kwargs) < 0) + return NULL; + + cbargs = PySequence_GetSlice(args, 2, len); + if (cbargs == NULL) + return NULL; + + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + handler_id = g_timeout_add_seconds_full(priority, interval, + _pyglib_handler_marshal, data, + _pyglib_destroy_notify); + return _PyLong_FromLong(handler_id); +} + +static gboolean +iowatch_marshal(GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + PyGILState_STATE state; + PyObject *tuple, *func, *firstargs, *args, *ret; + gboolean res; + + g_return_val_if_fail(user_data != NULL, FALSE); + + state = pyglib_gil_state_ensure(); + + tuple = (PyObject *)user_data; + func = PyTuple_GetItem(tuple, 0); + + /* arg vector is (fd, condtion, *args) */ + firstargs = Py_BuildValue("(Oi)", PyTuple_GetItem(tuple, 1), condition); + args = PySequence_Concat(firstargs, PyTuple_GetItem(tuple, 2)); + Py_DECREF(firstargs); + + ret = PyObject_CallObject(func, args); + Py_DECREF(args); + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + if (ret == Py_None) { + if (PyErr_Warn(PyExc_Warning, + "glib.io_add_watch callback returned None; " + "should return True/False")) { + PyErr_Print(); + } + } + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + pyglib_gil_state_release(state); + + return res; +} + +static PyObject * +pyglib_io_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *first, *pyfd, *callback, *cbargs = NULL, *data; + gint fd, priority = G_PRIORITY_DEFAULT, condition; + Py_ssize_t len; + GIOChannel *iochannel; + guint handler_id; + + len = PyTuple_Size(args); + if (len < 3) { + PyErr_SetString(PyExc_TypeError, + "io_add_watch requires at least 3 args"); + return NULL; + } + first = PySequence_GetSlice(args, 0, 3); + if (!PyArg_ParseTuple(first, "OiO:io_add_watch", &pyfd, &condition, + &callback)) { + Py_DECREF(first); + return NULL; + } + Py_DECREF(first); + fd = PyObject_AsFileDescriptor(pyfd); + if (fd < 0) { + return NULL; + } + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "third argument not callable"); + return NULL; + } + if (get_handler_priority(&priority, kwargs) < 0) + return NULL; + + cbargs = PySequence_GetSlice(args, 3, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(OON)", callback, pyfd, cbargs); + if (data == NULL) + return NULL; + iochannel = g_io_channel_unix_new(fd); + handler_id = g_io_add_watch_full(iochannel, priority, condition, + iowatch_marshal, data, + (GDestroyNotify)_pyglib_destroy_notify); + g_io_channel_unref(iochannel); + + return _PyLong_FromLong(handler_id); +} + +static PyObject * +pyglib_source_remove(PyObject *self, PyObject *args) +{ + guint tag; + + if (!PyArg_ParseTuple(args, "i:source_remove", &tag)) + return NULL; + + return PyBool_FromLong(g_source_remove(tag)); +} + +static PyObject * +pyglib_main_context_default(PyObject *unused) +{ + return pyglib_main_context_new(g_main_context_default()); +} + +static void +child_watch_func(GPid pid, gint status, gpointer data) +{ + struct _PyGChildData *child_data = (struct _PyGChildData *) data; + PyObject *retval; + PyGILState_STATE gil; + + gil = pyglib_gil_state_ensure(); + if (child_data->data) + retval = PyObject_CallFunction(child_data->func, "iiO", pid, status, + child_data->data); + else + retval = PyObject_CallFunction(child_data->func, "ii", pid, status); + + if (retval) + Py_DECREF(retval); + else + PyErr_Print(); + + pyglib_gil_state_release(gil); +} + +static void +child_watch_dnotify(gpointer data) +{ + struct _PyGChildData *child_data = (struct _PyGChildData *) data; + Py_DECREF(child_data->func); + Py_XDECREF(child_data->data); + g_slice_free(struct _PyGChildData, child_data); +} + + +static PyObject * +pyglib_child_watch_add(PyObject *unused, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "pid", "function", "data", "priority", NULL }; + guint id; + gint priority = G_PRIORITY_DEFAULT; + int pid; + PyObject *func, *user_data = NULL; + struct _PyGChildData *child_data; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "iO|Oi:glib.child_watch_add", kwlist, + &pid, &func, &user_data, &priority)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "glib.child_watch_add: second argument must be callable"); + return NULL; + } + + child_data = g_slice_new(struct _PyGChildData); + child_data->func = func; + child_data->data = user_data; + Py_INCREF(child_data->func); + if (child_data->data) + Py_INCREF(child_data->data); + id = g_child_watch_add_full(priority, pid, child_watch_func, + child_data, child_watch_dnotify); + return _PyLong_FromLong(id); +} + +static PyObject * +pyglib_markup_escape_text(PyObject *unused, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "text", NULL }; + char *text_in, *text_out; + Py_ssize_t text_size; + PyObject *retval; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "s#:glib.markup_escape_text", kwlist, + &text_in, &text_size)) + return NULL; + + text_out = g_markup_escape_text(text_in, text_size); + retval = _PyUnicode_FromString(text_out); + g_free(text_out); + return retval; +} + +static PyObject * +pyglib_get_current_time(PyObject *unused) +{ + GTimeVal timeval; + + g_get_current_time(&timeval); + return pyglib_float_from_timeval(timeval); +} + +static PyObject* +pyglib_get_user_cache_dir(PyObject *self) +{ + const char *path = g_get_user_cache_dir(); + + if (path) + return _PyUnicode_FromString(path); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject* +pyglib_get_user_config_dir(PyObject *self) +{ + const char *path = g_get_user_config_dir(); + + if (path) + return _PyUnicode_FromString(path); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject* +pyglib_get_user_data_dir(PyObject *self) +{ + const char *path = g_get_user_data_dir(); + + if (path) + return _PyUnicode_FromString(path); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject * +pyglib_get_user_special_dir(PyObject *unused, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "directory", NULL }; + guint directory; + const char *path; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:glib.get_user_special_dir", kwlist, + &directory)) + return NULL; + + path = g_get_user_special_dir(directory); + if (path) + return _PyUnicode_FromString(path); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject * +pyglib_main_depth(PyObject *unused) +{ + return _PyLong_FromLong(g_main_depth()); +} + +static PyObject * +pyglib_filename_display_name(PyObject *self, PyObject *args) +{ + PyObject *py_display_name; + char *filename, *display_name; + + if (!PyArg_ParseTuple(args, "s:glib.filename_display_name", + &filename)) + return NULL; + + display_name = g_filename_display_name(filename); + py_display_name = PyUnicode_DecodeUTF8(display_name, + strlen(display_name), NULL); + g_free(display_name); + return py_display_name; +} + +static PyObject * +pyglib_filename_display_basename(PyObject *self, PyObject *args) +{ + PyObject *py_display_basename; + char *filename, *display_basename; + + if (!PyArg_ParseTuple(args, "s:glib.filename_display_basename", + &filename)) + return NULL; + + display_basename = g_filename_display_basename(filename); + py_display_basename = PyUnicode_DecodeUTF8(display_basename, + strlen(display_basename), NULL); + g_free(display_basename); + return py_display_basename; +} + +static PyObject * +pyglib_filename_from_utf8(PyObject *self, PyObject *args) +{ + char *filename, *utf8string; + Py_ssize_t utf8string_len; + gsize bytes_written; + GError *error = NULL; + PyObject *py_filename; + + if (!PyArg_ParseTuple(args, "s#:glib.filename_from_utf8", + &utf8string, &utf8string_len)) + return NULL; + + filename = g_filename_from_utf8(utf8string, utf8string_len, + NULL, &bytes_written, &error); + if (pyglib_error_check(&error)) { + g_free(filename); + return NULL; + } + py_filename = _PyUnicode_FromStringAndSize(filename, bytes_written); + g_free(filename); + return py_filename; +} + + +static PyObject* +pyglib_get_application_name(PyObject *self) +{ + const char *name; + + name = g_get_application_name(); + if (!name) { + Py_INCREF(Py_None); + return Py_None; + } + return _PyUnicode_FromString(name); +} + +static PyObject* +pyglib_set_application_name(PyObject *self, PyObject *arg) +{ + if (!PyString_Check(arg)) { + PyErr_Format(PyExc_TypeError, + "first argument must be a string, not '%s'", + PyString_AS_STRING(PyObject_Repr(arg))); + return NULL; + } + g_set_application_name(PyString_AS_STRING(arg)); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +pyglib_get_prgname(PyObject *self) +{ + char *name; + + name = g_get_prgname(); + if (!name) { + Py_INCREF(Py_None); + return Py_None; + } + return _PyUnicode_FromString(name); +} + +static PyObject* +pyglib_set_prgname(PyObject *self, PyObject *arg) +{ + if (!PyString_Check(arg)) { + PyErr_Format(PyExc_TypeError, + "first argument must be a string, not '%s'", + PyString_AS_STRING(PyObject_Repr(arg))); + return NULL; + } + g_set_prgname(PyString_AS_STRING(arg)); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyglib_find_program_in_path(PyObject *unused, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "program", NULL }; + char *program, *ret; + PyObject *retval; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "s:glib.find_program_in_path", kwlist, + &program)) + return NULL; + + ret = g_find_program_in_path(program); + retval = _PyUnicode_FromString(ret); + g_free(ret); + return retval; +} + +static PyMethodDef _glib_functions[] = { + { "threads_init", + (PyCFunction) pyglib_threads_init, METH_NOARGS, + "threads_init()\n" + "Initialize GLib for use from multiple threads. If you also use GTK+\n" + "itself (i.e. GUI, not just PyGObject), use gtk.gdk.threads_init()\n" + "instead." }, + { "idle_add", + (PyCFunction)pyglib_idle_add, METH_VARARGS|METH_KEYWORDS, + "idle_add(callable, user_data=None, priority=None) -> source id\n" + " callable receives (user_data)\n" + "Adds a callable to be called whenever there are no higher priority\n" + "events pending to the default main loop." }, + { "timeout_add", + (PyCFunction)pyglib_timeout_add, METH_VARARGS|METH_KEYWORDS, + "timeout_add(interval, callable, user_data=None,\n" + " priority=None) -> source id\n" + " callable receives (user_data)\n" + "Sets a callable be called repeatedly until it returns False." }, + { "timeout_add_seconds", + (PyCFunction)pyglib_timeout_add_seconds, METH_VARARGS|METH_KEYWORDS, + "timeout_add(interval, callable, user_data=None,\n" + " priority=None) -> source_id\n" + " callable receives (user_data)\n" + "Sets a callable be called repeatedly until it returns False.\n" + "Use this if you want to have a timer in the \"seconds\" range\n" + "and do not care about the exact time of the first call of the\n" + "timer, use this for more efficient system power usage." }, + { "io_add_watch", + (PyCFunction)pyglib_io_add_watch, METH_VARARGS|METH_KEYWORDS, + "io_add_watch(fd, condition, callback, user_data=None) -> source id\n" + " callable receives (fd, condition, user_data)\n" + "Arranges for the fd to be monitored by the main loop for the\n" + "specified condition. Condition is a combination of glib.IO_IN,\n" + "glib.IO_OUT, glib.IO_PRI, gio.IO_ERR and gio.IO_HUB.\n" }, + { "child_watch_add", + (PyCFunction)pyglib_child_watch_add, METH_VARARGS|METH_KEYWORDS, + "child_watch_add(pid, callable, user_data=None,\n" + "priority=None) -> source id\n" + " callable receives (pid, condition, user_data)\n" + "Sets the function specified by function to be called with the user\n" + "data specified by data when the child indicated by pid exits.\n" + "Condition is a combination of glib.IO_IN, glib.IO_OUT, glib.IO_PRI,\n" + "gio.IO_ERR and gio.IO_HUB." }, + { "source_remove", + (PyCFunction)pyglib_source_remove, METH_VARARGS, + "source_remove(source_id) -> True if removed\n" + "Removes the event source specified by source id as returned by the\n" + "glib.idle_add(), glib.timeout_add() or glib.io_add_watch()\n" + "functions." }, + { "spawn_async", + (PyCFunction)pyglib_spawn_async, METH_VARARGS|METH_KEYWORDS, + "spawn_async(argv, envp=None, working_directory=None,\n" + " flags=0, child_setup=None, user_data=None,\n" + " standard_input=None, standard_output=None,\n" + " standard_error=None) -> (pid, stdin, stdout, stderr)\n" + "Execute a child program asynchronously within a glib.MainLoop()\n" + "See the reference manual for a complete reference." }, + { "main_context_default", + (PyCFunction)pyglib_main_context_default, METH_NOARGS, + "main_context_default() -> a main context\n" + "Returns the default main context. This is the main context used\n" + "for main loop functions when a main loop is not explicitly specified." }, + { "main_depth", + (PyCFunction)pyglib_main_depth, METH_NOARGS, + "main_depth() -> stack depth\n" + "Returns the depth of the stack of calls in the main context." }, + { "filename_display_name", + (PyCFunction)pyglib_filename_display_name, METH_VARARGS }, + { "filename_display_basename", + (PyCFunction)pyglib_filename_display_basename, METH_VARARGS }, + { "filename_from_utf8", + (PyCFunction)pyglib_filename_from_utf8, METH_VARARGS }, + { "get_application_name", + (PyCFunction)pyglib_get_application_name, METH_NOARGS }, + { "set_application_name", + (PyCFunction)pyglib_set_application_name, METH_O }, + { "get_prgname", + (PyCFunction)pyglib_get_prgname, METH_NOARGS }, + { "set_prgname", + (PyCFunction)pyglib_set_prgname, METH_O }, + { "get_current_time", + (PyCFunction)pyglib_get_current_time, METH_NOARGS }, + { "get_user_cache_dir", + (PyCFunction)pyglib_get_user_cache_dir, METH_NOARGS }, + { "get_user_config_dir", + (PyCFunction)pyglib_get_user_config_dir, METH_NOARGS }, + { "get_user_data_dir", + (PyCFunction)pyglib_get_user_data_dir, METH_NOARGS }, + { "get_user_special_dir", + (PyCFunction)pyglib_get_user_special_dir, METH_VARARGS|METH_KEYWORDS }, + { "markup_escape_text", + (PyCFunction)pyglib_markup_escape_text, METH_VARARGS|METH_KEYWORDS }, + { "find_program_in_path", + (PyCFunction)pyglib_find_program_in_path, METH_VARARGS|METH_KEYWORDS }, + { NULL, NULL, 0 } +}; + +/* ----------------- glib module initialisation -------------- */ + +static struct _PyGLib_Functions pyglib_api = { + FALSE, /* threads_enabled */ + NULL, /* gerror_exception */ + NULL, /* block_threads */ + NULL /* unblock_threads */ +}; + +static void +pyglib_register_api(PyObject *d) +{ + PyObject *o; + + /* for addon libraries ... */ + PyDict_SetItemString(d, "_PyGLib_API", + o=PyCObject_FromVoidPtr(&pyglib_api,NULL)); + Py_DECREF(o); + + pyglib_init_internal(o); +} + +static void +pyglib_register_error(PyObject *d) +{ + PyObject *dict; + PyObject *gerror_class; + dict = PyDict_New(); + /* This is a hack to work around the deprecation warning of + * BaseException.message in Python 2.6+. + * GError has also an "message" attribute. + */ + PyDict_SetItemString(dict, "message", Py_None); + gerror_class = PyErr_NewException("glib.GError", PyExc_RuntimeError, dict); + Py_DECREF(dict); + + PyDict_SetItemString(d, "GError", gerror_class); + pyglib_api.gerror_exception = gerror_class; +} + +static void +pyglib_register_version_tuples(PyObject *d) +{ + PyObject *o; + + /* glib version */ + o = Py_BuildValue("(iii)", glib_major_version, glib_minor_version, + glib_micro_version); + PyDict_SetItemString(d, "glib_version", o); + Py_DECREF(o); + + /* pyglib version */ + o = Py_BuildValue("(iii)", + PYGLIB_MAJOR_VERSION, + PYGLIB_MINOR_VERSION, + PYGLIB_MICRO_VERSION); + PyDict_SetItemString(d, "pyglib_version", o); + Py_DECREF(o); +} + +static void +pyglib_register_constants(PyObject *m) +{ + PyModule_AddIntConstant(m, "SPAWN_LEAVE_DESCRIPTORS_OPEN", + G_SPAWN_LEAVE_DESCRIPTORS_OPEN); + PyModule_AddIntConstant(m, "SPAWN_DO_NOT_REAP_CHILD", + G_SPAWN_DO_NOT_REAP_CHILD); + PyModule_AddIntConstant(m, "SPAWN_SEARCH_PATH", + G_SPAWN_SEARCH_PATH); + PyModule_AddIntConstant(m, "SPAWN_STDOUT_TO_DEV_NULL", + G_SPAWN_STDOUT_TO_DEV_NULL); + PyModule_AddIntConstant(m, "SPAWN_STDERR_TO_DEV_NULL", + G_SPAWN_STDERR_TO_DEV_NULL); + PyModule_AddIntConstant(m, "SPAWN_CHILD_INHERITS_STDIN", + G_SPAWN_CHILD_INHERITS_STDIN); + PyModule_AddIntConstant(m, "SPAWN_FILE_AND_ARGV_ZERO", + G_SPAWN_FILE_AND_ARGV_ZERO); + + PyModule_AddIntConstant(m, "PRIORITY_HIGH", + G_PRIORITY_HIGH); + PyModule_AddIntConstant(m, "PRIORITY_DEFAULT", + G_PRIORITY_DEFAULT); + PyModule_AddIntConstant(m, "PRIORITY_HIGH_IDLE", + G_PRIORITY_HIGH_IDLE); + PyModule_AddIntConstant(m, "PRIORITY_DEFAULT_IDLE", + G_PRIORITY_DEFAULT_IDLE); + PyModule_AddIntConstant(m, "PRIORITY_LOW", + G_PRIORITY_LOW); + + PyModule_AddIntConstant(m, "IO_IN", G_IO_IN); + PyModule_AddIntConstant(m, "IO_OUT", G_IO_OUT); + PyModule_AddIntConstant(m, "IO_PRI", G_IO_PRI); + PyModule_AddIntConstant(m, "IO_ERR", G_IO_ERR); + PyModule_AddIntConstant(m, "IO_HUP", G_IO_HUP); + PyModule_AddIntConstant(m, "IO_NVAL", G_IO_NVAL); + + PyModule_AddIntConstant(m, "IO_STATUS_ERROR", + G_IO_STATUS_ERROR); + PyModule_AddIntConstant(m, "IO_STATUS_NORMAL", + G_IO_STATUS_NORMAL); + PyModule_AddIntConstant(m, "IO_STATUS_EOF", + G_IO_STATUS_EOF); + PyModule_AddIntConstant(m, "IO_STATUS_AGAIN", + G_IO_STATUS_AGAIN); + PyModule_AddIntConstant(m, "IO_FLAG_APPEND", + G_IO_FLAG_APPEND); + PyModule_AddIntConstant(m, "IO_FLAG_NONBLOCK", + G_IO_FLAG_NONBLOCK); + PyModule_AddIntConstant(m, "IO_FLAG_IS_READABLE", + G_IO_FLAG_IS_READABLE); + PyModule_AddIntConstant(m, "IO_FLAG_IS_WRITEABLE", + G_IO_FLAG_IS_WRITEABLE); + PyModule_AddIntConstant(m, "IO_FLAG_IS_SEEKABLE", + G_IO_FLAG_IS_SEEKABLE); + PyModule_AddIntConstant(m, "IO_FLAG_MASK", + G_IO_FLAG_MASK); + PyModule_AddIntConstant(m, "IO_FLAG_GET_MASK", + G_IO_FLAG_GET_MASK); + PyModule_AddIntConstant(m, "IO_FLAG_SET_MASK", + G_IO_FLAG_SET_MASK); + + PyModule_AddIntConstant(m, "OPTION_FLAG_HIDDEN", + G_OPTION_FLAG_HIDDEN); + PyModule_AddIntConstant(m, "OPTION_FLAG_IN_MAIN", + G_OPTION_FLAG_IN_MAIN); + PyModule_AddIntConstant(m, "OPTION_FLAG_REVERSE", + G_OPTION_FLAG_REVERSE); + PyModule_AddIntConstant(m, "OPTION_FLAG_NO_ARG", + G_OPTION_FLAG_NO_ARG); + PyModule_AddIntConstant(m, "OPTION_FLAG_FILENAME", + G_OPTION_FLAG_FILENAME); + PyModule_AddIntConstant(m, "OPTION_FLAG_OPTIONAL_ARG", + G_OPTION_FLAG_OPTIONAL_ARG); + PyModule_AddIntConstant(m, "OPTION_FLAG_NOALIAS", + G_OPTION_FLAG_NOALIAS); + + PyModule_AddIntConstant(m, "OPTION_ERROR_UNKNOWN_OPTION", + G_OPTION_ERROR_UNKNOWN_OPTION); + PyModule_AddIntConstant(m, "OPTION_ERROR_BAD_VALUE", + G_OPTION_ERROR_BAD_VALUE); + PyModule_AddIntConstant(m, "OPTION_ERROR_FAILED", + G_OPTION_ERROR_FAILED); + + PyModule_AddIntConstant(m, "USER_DIRECTORY_DESKTOP", + G_USER_DIRECTORY_DESKTOP); + PyModule_AddIntConstant(m, "USER_DIRECTORY_DOCUMENTS", + G_USER_DIRECTORY_DOCUMENTS); + PyModule_AddIntConstant(m, "USER_DIRECTORY_DOWNLOAD", + G_USER_DIRECTORY_DOWNLOAD); + PyModule_AddIntConstant(m, "USER_DIRECTORY_MUSIC", + G_USER_DIRECTORY_MUSIC); + PyModule_AddIntConstant(m, "USER_DIRECTORY_PICTURES", + G_USER_DIRECTORY_PICTURES); + PyModule_AddIntConstant(m, "USER_DIRECTORY_PUBLIC_SHARE", + G_USER_DIRECTORY_PUBLIC_SHARE); + PyModule_AddIntConstant(m, "USER_DIRECTORY_TEMPLATES", + G_USER_DIRECTORY_TEMPLATES); + PyModule_AddIntConstant(m, "USER_DIRECTORY_VIDEOS", + G_USER_DIRECTORY_VIDEOS); + + PyModule_AddStringConstant(m, "OPTION_REMAINING", + G_OPTION_REMAINING); + PyModule_AddStringConstant(m, "OPTION_ERROR", + (char*) g_quark_to_string(G_OPTION_ERROR)); +} + +PYGLIB_MODULE_START(_glib, "glib._glib") +{ + PyObject *d = PyModule_GetDict(module); + + pyglib_register_constants(module); + pyglib_register_api(d); + pyglib_register_error(d); + pyglib_register_version_tuples(d); + pyglib_iochannel_register_types(d); + pyglib_mainloop_register_types(d); + pyglib_maincontext_register_types(d); + pyglib_source_register_types(d); + pyglib_spawn_register_types(d); + pyglib_option_context_register_types(d); + pyglib_option_group_register_types(d); +} +PYGLIB_MODULE_END diff --git a/glib/option.py b/glib/option.py new file mode 100644 index 0000000..027752f --- /dev/null +++ b/glib/option.py @@ -0,0 +1,350 @@ +# -*- Mode: Python -*- +# pygobject - Python bindings for the GObject library +# Copyright (C) 2006 Johannes Hoelzl +# +# glib/option.py: GOption command line parser +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA + +"""GOption command line parser + +Extends optparse to use the GOptionGroup, GOptionEntry and GOptionContext +objects. So it is possible to use the gtk, gnome_program and gstreamer command +line groups and contexts. + +Use this interface instead of the raw wrappers of GOptionContext and +GOptionGroup in glib. +""" + +import sys +import optparse +from optparse import OptParseError, OptionError, OptionValueError, \ + BadOptionError, OptionConflictError + +import glib +_glib = sys.modules['glib._glib'] + +__all__ = [ + "OptParseError", + "OptionError", + "OptionValueError", + "BadOptionError", + "OptionConflictError" + "Option", + "OptionGroup", + "OptionParser", + "make_option", +] + +class Option(optparse.Option): + """Represents a command line option + + To use the extended possibilities of the GOption API Option + (and make_option) are extended with new types and attributes. + + Types: + filename The supplied arguments are read as filename, GOption + parses this type in with the GLib filename encoding. + + Attributes: + optional_arg This does not need a arguement, but it can be supplied. + hidden The help list does not show this option + in_main This option apears in the main group, this should only + be used for backwards compatibility. + + Use Option.REMAINING as option name to get all positional arguments. + + NOTE: Every argument to an option is passed as utf-8 coded string, the only + exception are options which use the 'filename' type, its arguments + are passed as strings in the GLib filename encoding. + + For further help, see optparse.Option. + """ + TYPES = optparse.Option.TYPES + ( + 'filename', + ) + + ATTRS = optparse.Option.ATTRS + [ + 'hidden', + 'in_main', + 'optional_arg', + ] + + REMAINING = '--' + _glib.OPTION_REMAINING + + def __init__(self, *args, **kwargs): + optparse.Option.__init__(self, *args, **kwargs) + if not self._long_opts: + raise ValueError("%s at least one long option name.") + + if len(self._long_opts) < len(self._short_opts): + raise ValueError( + "%s at least more long option names than short option names.") + + if not self.help: + raise ValueError("%s needs a help message.", self._long_opts[0]) + + + def _set_opt_string(self, opts): + if self.REMAINING in opts: + self._long_opts.append(self.REMAINING) + optparse.Option._set_opt_string(self, opts) + if len(self._short_opts) > len(self._long_opts): + raise OptionError("goption.Option needs more long option names " + "than short option names") + + def _to_goptionentries(self): + flags = 0 + + if self.hidden: + self.flags |= _glib.OPTION_FLAG_HIDDEN + + if self.in_main: + self.flags |= _glib.OPTION_FLAG_IN_MAIN + + if self.takes_value(): + if self.optional_arg: + flags |= _glib.OPTION_FLAG_OPTIONAL_ARG + else: + flags |= _glib.OPTION_FLAG_NO_ARG + + if self.type == 'filename': + flags |= _glib.OPTION_FLAG_FILENAME + + for (long_name, short_name) in zip(self._long_opts, self._short_opts): + yield (long_name[2:], short_name[1], flags, self.help, self.metavar) + + for long_name in self._long_opts[len(self._short_opts):]: + yield (long_name[2:], '\0', flags, self.help, self.metavar) + +class OptionGroup(optparse.OptionGroup): + """A group of command line options. + + Arguements: + name: The groups name, used to create the + --help-{name} option + description: Shown as title of the groups help view + help_description: Shown as help to the --help-{name} option + option_list: The options used in this group, must be option.Option() + defaults: A dicitionary of default values + translation_domain: Sets the translation domain for gettext(). + + NOTE: This OptionGroup does not exactly map the optparse.OptionGroup + interface. There is no parser object to supply, but it is possible + to set default values and option_lists. Also the default values and + values are not shared with the OptionParser. + + To pass a OptionGroup into a function which expects a GOptionGroup (e.g. + gnome_program_init() ). OptionGroup.get_option_group() can be used. + + For further help, see optparse.OptionGroup. + """ + def __init__(self, name, description, help_description="", + option_list=None, defaults=None, + translation_domain=None): + optparse.OptionContainer.__init__(self, Option, 'error', description) + self.name = name + self.parser = None + self.help_description = help_description + if defaults: + self.defaults = defaults + + self.values = None + + self.translation_domain = translation_domain + + if option_list: + for option in option_list: + self.add_option(option) + + def _create_option_list(self): + self.option_list = [] + self._create_option_mappings() + + def _to_goptiongroup(self, parser): + def callback(option_name, option_value, group): + if option_name.startswith('--'): + opt = self._long_opt[option_name] + else: + opt = self._short_opt[option_name] + + try: + opt.process(option_name, option_value, self.values, parser) + except OptionValueError: + error = sys.exc_info()[1] + gerror = _glib.GError(str(error)) + gerror.domain = _glib.OPTION_ERROR + gerror.code = _glib.OPTION_ERROR_BAD_VALUE + gerror.message = str(error) + raise gerror + + group = _glib.OptionGroup(self.name, self.description, + self.help_description, callback) + if self.translation_domain: + group.set_translation_domain(self.translation_domain) + + entries = [] + for option in self.option_list: + entries.extend(option._to_goptionentries()) + group.add_entries(entries) + + return group + + def get_option_group(self, parser = None): + """ Returns the corresponding GOptionGroup object. + + Can be used as parameter for gnome_program_init(), gtk_init(). + """ + self.set_values_to_defaults() + return self._to_goptiongroup(parser) + + def set_values_to_defaults(self): + for option in self.option_list: + default = self.defaults.get(option.dest) + if isinstance(default, basestring): + opt_str = option.get_opt_string() + self.defaults[option.dest] = option.check_value( + opt_str, default) + self.values = optparse.Values(self.defaults) + +class OptionParser(optparse.OptionParser): + """Command line parser with GOption support. + + NOTE: The OptionParser interface is not the exactly the same as the + optparse.OptionParser interface. Especially the usage parameter + is only used to show the metavar of the arguements. + + Attribues: + help_enabled: The --help, --help-all and --help-{group} + options are enabled (default). + ignore_unknown_options: Do not throw a exception when a option is not + knwon, the option will be in the result list. + + OptionParser.add_option_group() does not only accept OptionGroup instances + but also glib.OptionGroup, which is returned by gtk_get_option_group(). + + Only glib.option.OptionGroup and glib.option.Option instances should + be passed as groups and options. + + For further help, see optparse.OptionParser. + """ + + def __init__(self, *args, **kwargs): + if 'option_class' not in kwargs: + kwargs['option_class'] = Option + self.help_enabled = kwargs.pop('help_enabled', True) + self.ignore_unknown_options = kwargs.pop('ignore_unknown_options', + False) + optparse.OptionParser.__init__(self, add_help_option=False, + *args, **kwargs) + + def set_usage(self, usage): + if usage is None: + self.usage = '' + elif usage.startswith("%prog"): + self.usage = usage[len("%prog"):] + else: + self.usage = usage + + def _to_goptioncontext(self, values): + if self.description: + parameter_string = self.usage + " - " + self.description + else: + parameter_string = self.usage + context = _glib.OptionContext(parameter_string) + context.set_help_enabled(self.help_enabled) + context.set_ignore_unknown_options(self.ignore_unknown_options) + + for option_group in self.option_groups: + if isinstance(option_group, _glib.OptionGroup): + g_group = option_group + else: + g_group = option_group.get_option_group(self) + context.add_group(g_group) + + def callback(option_name, option_value, group): + if option_name.startswith('--'): + opt = self._long_opt[option_name] + else: + opt = self._short_opt[option_name] + opt.process(option_name, option_value, values, self) + + main_group = _glib.OptionGroup(None, None, None, callback) + main_entries = [] + for option in self.option_list: + main_entries.extend(option._to_goptionentries()) + main_group.add_entries(main_entries) + context.set_main_group(main_group) + + return context + + def add_option_group(self, *args, **kwargs): + if isinstance(args[0], basestring): + optparse.OptionParser.add_option_group(self, + OptionGroup(self, *args, **kwargs)) + return + elif len(args) == 1 and not kwargs: + if isinstance(args[0], OptionGroup): + if not args[0].parser: + args[0].parser = self + if args[0].parser is not self: + raise ValueError("invalid OptionGroup (wrong parser)") + if isinstance(args[0], _glib.OptionGroup): + self.option_groups.append(args[0]) + return + optparse.OptionParser.add_option_group(self, *args, **kwargs) + + def _get_all_options(self): + options = self.option_list[:] + for group in self.option_groups: + if isinstance(group, optparse.OptionGroup): + options.extend(group.option_list) + return options + + def _process_args(self, largs, rargs, values): + context = self._to_goptioncontext(values) + + # _process_args() returns the remaining parameters in rargs. + # The prepended program name is used to all g_set_prgname() + # The program name is cut away so it doesn't appear in the result. + rargs[:] = context.parse([sys.argv[0]] + rargs)[1:] + + def parse_args(self, args=None, values=None): + old_args = args or [] + try: + options, args = optparse.OptionParser.parse_args( + self, args, values) + except _glib.GError: + error = sys.exc_info()[1] + if error.domain != _glib.OPTION_ERROR: + raise + if error.code == _glib.OPTION_ERROR_BAD_VALUE: + raise OptionValueError(error.message) + elif error.code == _glib.OPTION_ERROR_UNKNOWN_OPTION: + raise BadOptionError(error.message) + elif error.code == _glib.OPTION_ERROR_FAILED: + raise OptParseError(error.message) + else: + raise + + for group in self.option_groups: + for key, value in group.values.__dict__.items(): + options.ensure_value(key, value) + + args = args[2:-len(old_args)] + return options, args + +make_option = Option diff --git a/glib/pygiochannel.c b/glib/pygiochannel.c new file mode 100644 index 0000000..4c935e8 --- /dev/null +++ b/glib/pygiochannel.c @@ -0,0 +1,740 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <Python.h> +#include <pythread.h> +#include <structmember.h> /* for PyMemberDef */ + +#include "pyglib.h" +#include "pyglib-private.h" +#include "pygsource.h" + +typedef struct { + PyObject_HEAD + GIOChannel *channel; + int softspace; /* to make print >> chan, "foo" ... work */ +} PyGIOChannel; + +PYGLIB_DEFINE_TYPE("glib.IOChannel", PyGIOChannel_Type, PyGIOChannel) + +static PyObject* +py_io_channel_next(PyGIOChannel *self) +{ + PyObject* ret_obj = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + GIOStatus status; + + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) + return NULL; + + if (status == G_IO_STATUS_EOF) { + PyErr_SetString(PyExc_StopIteration, "EOF"); + return NULL; + } + + ret_obj = _PyUnicode_FromStringAndSize(str_return, length); + g_free(str_return); + return ret_obj; +} + +static int +py_io_channel_compare(PyGIOChannel *self, PyGIOChannel *v) +{ + if (self->channel == v->channel) return 0; + if (self->channel > v->channel) return -1; + return 1; +} + +static PyObject* +py_io_channel_get_iter(PyObject *self) +{ + Py_INCREF(self); + return self; +} + +static long +py_io_channel_hash(PyGIOChannel *self) +{ + return (long) self->channel; +} + +static void +py_io_channel_dealloc(PyGIOChannel *self) +{ + if (self->channel) + g_io_channel_unref(self->channel); + PyObject_DEL(self); +} + +static PyObject* +py_io_channel_shutdown(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "flush", NULL }; + GIOStatus ret; + PyObject* flush = Py_True; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:glib.IOChannel.shutdown", kwlist, &flush)) + return NULL; + + ret = g_io_channel_shutdown(self->channel, PyObject_IsTrue(flush), &error); + if (pyglib_error_check(&error)) + return NULL; + + return _PyLong_FromLong(ret); +} + +/* character encoding conversion involved functions. + */ + +static PyObject* +py_io_channel_set_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + int size; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:glib.IOChannel.set_buffer_size", kwlist, &size)) + return NULL; + + g_io_channel_set_buffer_size(self->channel, size); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_buffer_size(PyGIOChannel* self) +{ + return _PyLong_FromLong(g_io_channel_get_buffer_size(self->channel)); +} + +static PyObject* +py_io_channel_set_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "buffered", NULL }; + int buffered; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:glib.IOChannel.set_buffered", kwlist, &buffered)) + return NULL; + + g_io_channel_set_buffered(self->channel, buffered); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_buffered(PyGIOChannel* self) +{ + return _PyLong_FromLong(g_io_channel_get_buffered(self->channel)); +} + +static PyObject* +py_io_channel_set_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "encoding", NULL }; + const char* encoding; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:glib.IOChannel.set_encoding", kwlist, &encoding)) + return NULL; + + g_io_channel_set_encoding(self->channel, encoding, &error); + if (pyglib_error_check(&error)) + return NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_encoding(PyGIOChannel* self) +{ + const char* encoding = g_io_channel_get_encoding(self->channel); + + if (encoding == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + return _PyUnicode_FromString(encoding); +} + +#define CHUNK_SIZE (8 * 1024) + +static PyObject* +py_io_channel_read_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "max_count", NULL }; + int max_count = -1; + PyObject* ret_obj = NULL; + gsize total_read = 0; + GError* error = NULL; + GIOStatus status = G_IO_STATUS_NORMAL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:glib.IOChannel.read", kwlist, &max_count)) + return NULL; + + if (max_count == 0) + return _PyUnicode_FromString(""); + + while (status == G_IO_STATUS_NORMAL + && (max_count == -1 || total_read < max_count)) { + gsize single_read; + char* buf; + gsize buf_size; + + if (max_count == -1) + buf_size = CHUNK_SIZE; + else { + buf_size = max_count - total_read; + if (buf_size > CHUNK_SIZE) + buf_size = CHUNK_SIZE; + } + + if ( ret_obj == NULL ) { + ret_obj = _PyUnicode_FromStringAndSize((char *)NULL, buf_size); + if (ret_obj == NULL) + goto failure; + } + else if (buf_size + total_read > _PyUnicode_GET_SIZE(ret_obj)) { + if (_PyUnicode_Resize(&ret_obj, buf_size + total_read) == -1) + goto failure; + } + + buf = _PyUnicode_AS_STRING(ret_obj) + total_read; + + pyglib_unblock_threads(); + status = g_io_channel_read_chars(self->channel, buf, buf_size, + &single_read, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + goto failure; + + total_read += single_read; + } + + if ( total_read != _PyUnicode_GET_SIZE(ret_obj) ) { + if (_PyUnicode_Resize(&ret_obj, total_read) == -1) + goto failure; + } + return ret_obj; + + failure: + Py_XDECREF(ret_obj); + return NULL; +} + +static PyObject* +py_io_channel_write_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "buf", NULL }; + const char* buf; + Py_ssize_t buf_len; + gsize count; + GError* error = NULL; + GIOStatus status; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:glib.IOChannel.write", + kwlist, &buf, &buf_len)) + return NULL; + + pyglib_unblock_threads(); + status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + return NULL; + + return _PyLong_FromLong(count); +} + +static PyObject* +py_io_channel_write_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "lines", NULL }; + char *buf; + Py_ssize_t buf_len; + gsize count; + GError* error = NULL; + GIOStatus status; + PyObject *iter, *value, *pylines; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:glib.IOChannel.writelines", + kwlist, &pylines)) + return NULL; + + iter = PyObject_GetIter(pylines); + + while (1) { + value = PyIter_Next(iter); + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + PyErr_Clear(); + goto normal_exit; + } + if (!_PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, "glib.IOChannel.writelines must" + " be sequence/iterator of strings"); + Py_DECREF(iter); + return NULL; + } + _PyUnicode_AsStringAndSize(value, &buf, &buf_len); + pyglib_unblock_threads(); + status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); + pyglib_unblock_threads(); + Py_DECREF(value); + if (pyglib_error_check(&error)) { + Py_DECREF(iter); + return NULL; + } + } +normal_exit: + Py_DECREF(iter); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_flush(PyGIOChannel* self) +{ + GError* error = NULL; + GIOStatus status; + + pyglib_unblock_threads(); + status = g_io_channel_flush(self->channel, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + return NULL; + + return _PyLong_FromLong(status); +} + +static PyObject* +py_io_channel_set_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "flags", NULL }; + GIOFlags flags; + GIOStatus status; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:glib.IOChannel.set_flags", + kwlist, &flags)) + return NULL; + + status = g_io_channel_set_flags(self->channel, flags, &error); + if (pyglib_error_check(&error)) + return NULL; + + return _PyLong_FromLong(status); +} + +static PyObject* +py_io_channel_get_flags(PyGIOChannel* self) +{ + return _PyLong_FromLong(g_io_channel_get_flags(self->channel)); +} + +static PyObject* +py_io_channel_get_buffer_condition(PyGIOChannel* self) +{ + return _PyLong_FromLong(g_io_channel_get_buffer_condition(self->channel)); +} + +static PyObject* +py_io_channel_set_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "do_close", NULL }; + PyObject *do_close; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:glib.IOChannel.set_close_on_unref", + kwlist, &do_close)) + return NULL; + + g_io_channel_set_close_on_unref(self->channel, PyObject_IsTrue(do_close)); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_close_on_unref(PyGIOChannel* self) +{ + if (g_io_channel_get_close_on_unref(self->channel)) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +typedef struct { + PyObject *callback; + PyObject *iochannel; + PyObject *user_data; +} PyGIOWatchData; + +static void +pyg_iowatch_data_free(PyGIOWatchData *data) +{ + Py_DECREF(data->callback); + Py_XDECREF(data->user_data); + Py_DECREF(data->iochannel); + g_slice_free(PyGIOWatchData, data); +} + +static gboolean +pyg_iowatch_marshal(GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + PyObject *ret; + gboolean res; + PyGIOWatchData *data = (PyGIOWatchData *) user_data; + PyGILState_STATE state; + + g_return_val_if_fail(user_data != NULL, FALSE); + g_return_val_if_fail(((PyGIOChannel *) data->iochannel)->channel == source, + FALSE); + + state = pyglib_gil_state_ensure(); + + if (data->user_data) + ret = PyObject_CallFunction(data->callback, "OiO", data->iochannel, + condition, data->user_data); + else + ret = PyObject_CallFunction(data->callback, "Oi", data->iochannel, + condition); + + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + pyglib_gil_state_release(state); + + return res; +} + + + +static PyObject * +py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "condition", "callback", "user_data", "priority", NULL }; + PyObject *callback, *user_data = NULL; + int priority = G_PRIORITY_DEFAULT, condition; + GIOChannel *iochannel = NULL; + guint handler_id; + PyGIOWatchData *data; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "iO|Oi:glib.IOChannel.add_watch", + kwlist, &condition, &callback, + &user_data, &priority)) + return NULL; + + iochannel = ((PyGIOChannel *) self)->channel; + + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "second must be callable"); + return NULL; + } + + data = g_slice_new(PyGIOWatchData); + data->callback = callback; Py_INCREF(callback); + data->user_data = user_data; Py_XINCREF(user_data); + data->iochannel = self; Py_INCREF(self); + + handler_id = g_io_add_watch_full(((PyGIOChannel *) self)->channel, + priority, condition, + pyg_iowatch_marshal, data, + (GDestroyNotify) pyg_iowatch_data_free); + return PyLong_FromUnsignedLong(handler_id); +} + + +#ifdef G_OS_WIN32 + +static PyObject * +py_io_channel_win32_poll(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fds", "timeout", NULL }; + GPollFD *pollfd; + PyObject *pyfds, *pyfd; + guint len, i; + gint timeout = -1; + gint result; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|i:glib.IOChannel.win32_poll", + kwlist, &PyList_Type, &pyfds, &timeout)) + return NULL; + + len = PyList_Size(pyfds); + pollfd = g_newa(GPollFD, len); + for (i = 0; i < len; ++i) { + pyfd = PyList_GET_ITEM(pyfds, i); + if (!PyObject_TypeCheck(pyfd, &PyGPollFD_Type)) { + PyErr_SetString(PyExc_TypeError, "'fds' must be a list of glib.PollFD objects"); + return NULL; + } + pollfd[i] = ((PyGPollFD *) pyfd)->pollfd; + } + + result = g_io_channel_win32_poll(pollfd, len, timeout); + for (i = 0; i < len; ++i) { + pyfd = PyList_GET_ITEM(pyfds, i); + ((PyGPollFD *) pyfd)->pollfd = pollfd[i]; + } + return _PyLong_FromLong(result); +} + +static PyObject * +py_io_channel_win32_make_pollfd(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "condition", NULL }; + int condition; + GPollFD pollfd; + PyGPollFD *pypollfd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:glib.IOChannel.win32_make_pollfd", + kwlist, &condition)) + return NULL; + + g_io_channel_win32_make_pollfd(((PyGIOChannel *) self)->channel, + condition, &pollfd); + pypollfd = PyObject_NEW(PyGPollFD, &PyGPollFD_Type); + pypollfd->pollfd = pollfd; + return (PyObject *) pypollfd; +} +#endif /* def G_OS_WIN32 */ + + +static PyObject* +py_io_channel_read_line(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + PyObject* ret_obj = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + gint size_hint = -1; + GIOStatus status; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:glib.IOChannel.readline", kwlist, + &size_hint)) + return NULL; + + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) + return NULL; + ret_obj = _PyUnicode_FromStringAndSize(str_return, length); + g_free(str_return); + return ret_obj; +} + +static PyObject* +py_io_channel_read_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + PyObject *line = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + gint size_hint = -1; + GIOStatus status = G_IO_STATUS_NORMAL; + PyObject *list; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:glib.IOChannel.readlines", kwlist, + &size_hint)) + return NULL; + + list = PyList_New(0); + while (status == G_IO_STATUS_NORMAL) { + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) { + Py_DECREF(line); + return NULL; + } + line = _PyUnicode_FromStringAndSize(str_return, length); + g_free(str_return); + if (PyList_Append(list, line)) { + Py_DECREF(line); + Py_DECREF(list); + return NULL; + } + } + return list; +} + + +static PyObject* +py_io_channel_seek(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "offset", "whence", NULL }; + gint64 offset; + int whence = 0; + GIOStatus status; + GSeekType seek_type; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "L|i:glib.IOChannel.seek", + kwlist, &offset, &whence)) + return NULL; + + switch (whence) + { + case 0: seek_type = G_SEEK_SET; break; + case 1: seek_type = G_SEEK_CUR; break; + case 2: seek_type = G_SEEK_END; break; + default: + PyErr_SetString(PyExc_ValueError, "invalid 'whence' value"); + return NULL; + } + + status = g_io_channel_seek_position(self->channel, offset, + seek_type, &error); + if (pyglib_error_check(&error)) + return NULL; + + return _PyLong_FromLong(status); +} + +#if 0 // Not wrapped +void g_io_channel_set_line_term (GIOChannel *channel, + const gchar *line_term, + gint length); + +G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel, + gint *length); + + + +GIOStatus g_io_channel_read_line_string (GIOChannel *channel, + GString *buffer, + gsize *terminator_pos, + GError **error); +GIOStatus g_io_channel_read_to_end (GIOChannel *channel, + gchar **str_return, + gsize *length, + GError **error); +GIOStatus g_io_channel_read_unichar (GIOChannel *channel, + gunichar *thechar, + GError **error); +GIOStatus g_io_channel_write_unichar (GIOChannel *channel, + gunichar thechar, + GError **error); +#endif // Not wrapped + +static PyMemberDef py_io_channel_members[] = { + { "softspace", T_INT, offsetof(PyGIOChannel, softspace), 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static PyMethodDef py_io_channel_methods[] = { + { "close", (PyCFunction)py_io_channel_shutdown, METH_KEYWORDS }, + { "flush", (PyCFunction)py_io_channel_flush, METH_NOARGS }, + { "set_encoding", (PyCFunction)py_io_channel_set_encoding, METH_KEYWORDS }, + { "get_encoding", (PyCFunction)py_io_channel_get_encoding, METH_NOARGS }, + { "set_buffered", (PyCFunction)py_io_channel_set_buffered, METH_KEYWORDS }, + { "get_buffered", (PyCFunction)py_io_channel_get_buffered, METH_NOARGS }, + { "set_buffer_size", (PyCFunction)py_io_channel_set_buffer_size, METH_KEYWORDS }, + { "get_buffer_size", (PyCFunction)py_io_channel_get_buffer_size, METH_NOARGS }, + { "read", (PyCFunction)py_io_channel_read_chars, METH_KEYWORDS }, + { "readline", (PyCFunction)py_io_channel_read_line, METH_KEYWORDS }, + { "readlines", (PyCFunction)py_io_channel_read_lines, METH_KEYWORDS }, + { "write", (PyCFunction)py_io_channel_write_chars, METH_KEYWORDS }, + { "writelines", (PyCFunction)py_io_channel_write_lines, METH_KEYWORDS }, + { "set_flags", (PyCFunction)py_io_channel_set_flags, METH_KEYWORDS }, + { "get_flags", (PyCFunction)py_io_channel_get_flags, METH_NOARGS }, + { "get_buffer_condition", (PyCFunction)py_io_channel_get_buffer_condition, METH_NOARGS }, + { "set_close_on_unref", (PyCFunction)py_io_channel_set_close_on_unref, METH_KEYWORDS }, + { "get_close_on_unref", (PyCFunction)py_io_channel_get_close_on_unref, METH_NOARGS }, + { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_KEYWORDS }, + { "seek", (PyCFunction)py_io_channel_seek, METH_KEYWORDS }, +#ifdef G_OS_WIN32 + { "win32_make_pollfd", (PyCFunction)py_io_channel_win32_make_pollfd, METH_KEYWORDS }, + { "win32_poll", (PyCFunction)py_io_channel_win32_poll, METH_KEYWORDS|METH_STATIC }, +#endif + { NULL, NULL, 0 } +}; + + +static int +py_io_channel_init(PyGIOChannel *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "filedes", "filename", "mode", +#ifdef G_OS_WIN32 + "hwnd", +#endif + NULL }; + int fd = -1; + char *mode = "r", *filename = NULL; + GError *error = NULL; +#ifdef G_OS_WIN32 + guint hwnd = 0; +#endif + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iss" +#ifdef G_OS_WIN32 + "I" +#endif + ":glib.IOChannel.__init__", + kwlist, &fd, &filename, &mode +#ifdef G_OS_WIN32 + , &hwnd +#endif + )) + return -1; + + if (fd != -1) + self->channel = g_io_channel_unix_new(fd); + else if (filename != NULL) { + self->channel = g_io_channel_new_file(filename, mode, &error); + if (pyglib_error_check(&error)) + return -1; + } +#ifdef G_OS_WIN32 + else if (hwnd != 0) { + self->channel = g_io_channel_win32_new_messages(hwnd); + } +#endif + else { +#ifdef G_OS_WIN32 + PyErr_SetString(PyExc_TypeError, "either a valid file descriptor, " + "file name, or window handle must be supplied"); +#else + PyErr_SetString(PyExc_TypeError, "either a valid file descriptor " + "or file name must be supplied"); +#endif + return -1; + } + return 0; +} + +void +pyglib_iochannel_register_types(PyObject *d) +{ + PyGIOChannel_Type.tp_init = (initproc)py_io_channel_init; + PyGIOChannel_Type.tp_dealloc = (destructor)py_io_channel_dealloc; + PyGIOChannel_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyGIOChannel_Type.tp_members = py_io_channel_members; + PyGIOChannel_Type.tp_methods = py_io_channel_methods; + PyGIOChannel_Type.tp_hash = (hashfunc)py_io_channel_hash; + PyGIOChannel_Type.tp_compare = (cmpfunc)py_io_channel_compare; + PyGIOChannel_Type.tp_iter = (getiterfunc)py_io_channel_get_iter; + PyGIOChannel_Type.tp_iternext = (iternextfunc)py_io_channel_next; + + PYGLIB_REGISTER_TYPE(d, PyGIOChannel_Type, "IOChannel"); +} diff --git a/glib/pygiochannel.h b/glib/pygiochannel.h new file mode 100644 index 0000000..9b03edd --- /dev/null +++ b/glib/pygiochannel.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_IOCHANNEL_H__ +#define __PYG_IOCHANNEL_H__ + +extern PyTypeObject PyGIOChannel_Type; + +void pyglib_iochannel_register_types(PyObject *d); + +#endif /* __PYG_IOCHANNEL_H__ */ diff --git a/glib/pyglib-private.h b/glib/pyglib-private.h new file mode 100644 index 0000000..8b033e1 --- /dev/null +++ b/glib/pyglib-private.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGLIB_PRIVATE_H__ +#define __PYGLIB_PRIVATE_H__ + +#include <Python.h> +#include <glib.h> + +#include <pyglib-python-compat.h> + +G_BEGIN_DECLS + +struct _PyGLib_Functions { + gboolean threads_enabled; + PyObject *gerror_exception; + PyGLibThreadBlockFunc block_threads; + PyGLibThreadBlockFunc unblock_threads; +}; + +gboolean _pyglib_handler_marshal(gpointer user_data); +void _pyglib_destroy_notify(gpointer user_data); + +G_END_DECLS + +#endif /* __PYGLIB_PRIVATE_H__ */ + + diff --git a/glib/pyglib-python-compat.h b/glib/pyglib-python-compat.h new file mode 100644 index 0000000..915a912 --- /dev/null +++ b/glib/pyglib-python-compat.h @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGLIB_PYTHON_COMPAT_H__ +#define __PYGLIB_PYTHON_COMPAT_H__ + +/* Python 2.3 does not define Py_CLEAR */ +#ifndef Py_CLEAR +#define Py_CLEAR(op) \ + do { \ + if (op) { \ + PyObject *tmp = (PyObject *)(op); \ + (op) = NULL; \ + Py_DECREF(tmp); \ + } \ + } while (0) +#endif + +/* Compilation on Python 2.4 */ +#if PY_VERSION_HEX < 0x02050000 +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +typedef inquiry lenfunc; +#endif + +/* Compilation on Python 2.x */ +#if PY_VERSION_HEX < 0x03000000 +#define RO READONLY +#define _PyUnicode_Check PyString_Check +#define _PyUnicode_AsString PyString_AsString +#define _PyUnicode_AsStringAndSize PyString_AsStringAndSize +#define _PyUnicode_FromString PyString_FromString +#define _PyUnicode_FromStringAndSize PyString_FromStringAndSize +#define _PyUnicode_FromFormat PyString_FromFormat +#define _PyUnicode_AS_STRING PyString_AS_STRING +#define _PyUnicode_GET_SIZE PyString_GET_SIZE +#define _PyUnicode_Resize _PyString_Resize +#define _PyUnicode_Type PyString_Type +#define _PyLong_Check PyInt_Check +#define _PyLong_FromLong PyInt_FromLong +#define _PyLong_AsLong PyInt_AsLong +#define _PyLongObject PyIntObject +#define _PyLong_Type PyInt_Type +#define _PyLong_AS_LONG PyInt_AS_LONG +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#else +#undef PYGLIB_MODULE_START +#undef PYGLIB_MODULE_END +#undef PYGLIB_DEFINE_TYPE +#undef PYGLIB_REGISTER_TYPE + +#define PYGLIB_MODULE_START(symbol, modname) \ + static struct PyModuleDef _##symbol##module = { \ + PyModuleDef_HEAD_INIT, \ + modname, \ + NULL, \ + -1, \ + symbol##_functions, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +}; \ +PyMODINIT_FUNC PyInit_##symbol(void) \ +{ \ + PyObject *module; \ + module = PyModule_Create(&_##symbol##module); +#define PYGLIB_MODULE_END return module; } +#define PYGLIB_DEFINE_TYPE(typename, symbol, csymbol) \ +PyTypeObject symbol = { \ + PyVarObject_HEAD_INIT(NULL, 0) \ + typename, \ + sizeof(csymbol) \ +}; +#define PYGLIB_REGISTER_TYPE(d, type, name) \ + if (!type.tp_alloc) \ + type.tp_alloc = PyType_GenericAlloc; \ + if (!type.tp_new) \ + type.tp_new = PyType_GenericNew; \ + if (PyType_Ready(&type)) \ + return; \ + PyDict_SetItemString(d, name, (PyObject *)&type); + +#define _PyUnicode_Check PyUnicode_Check +#define _PyUnicode_AsString PyUnicode_AsString +#define _PyUnicode_AsStringAndSize(obj, buf, size) PyUnicode_AsStringAndSize(obj, size) +#define _PyUnicode_FromString PyUnicode_FromString +#define _PyUnicode_FromStringAndSize PyUnicode_FromStringAndSize +#define _PyUnicode_FromFormat PyUnicode_FromFormat +#define _PyUnicode_AS_STRING _PyUnicode_AsString +#define _PyUnicode_GET_SIZE PyUnicode_GET_SIZE +#define _PyUnicode_Resize PyUnicode_Resize +#define _PyUnicode_Type PyUnicode_Type +#define _PyLong_Check PyLong_Check +#define _PyLong_FromLong PyLong_FromLong +#define _PyLong_AsLong PyLong_AsLong +#define _PyLong_AS_LONG PyLong_AS_LONG +#define _PyLongObject PyLongObject +#define _PyLong_Type PyLong_Type +#endif + +#endif /* __PYGLIB_PYTHON_COMPAT_H__ */ diff --git a/glib/pyglib.c b/glib/pyglib.c new file mode 100644 index 0000000..a1bdbb9 --- /dev/null +++ b/glib/pyglib.c @@ -0,0 +1,577 @@ +/* -*- Mode: C; c-set-style: python; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <Python.h> +#include <pythread.h> +#include "pyglib.h" +#include "pyglib-private.h" +#include "pygmaincontext.h" +#include "pygoptioncontext.h" +#include "pygoptiongroup.h" + +static struct _PyGLib_Functions *_PyGLib_API; +static int pyglib_thread_state_tls_key; +static PyObject *exception_table = NULL; + +static PyTypeObject *_PyGMainContext_Type; +#define PyGMainContext_Type (*_PyGMainContext_Type) + +static PyTypeObject *_PyGOptionGroup_Type; +#define PyGOptionGroup_Type (*_PyGOptionGroup_Type) + +static PyTypeObject *_PyGOptionContext_Type; +#define PyGOptionContext_Type (*_PyGOptionContext_Type) + +void +pyglib_init(void) +{ + PyObject *glib, *cobject; + + glib = PyImport_ImportModule("glib"); + if (!glib) { + if (PyErr_Occurred()) { + PyObject *type, *value, *traceback; + PyObject *py_orig_exc; + PyErr_Fetch(&type, &value, &traceback); + py_orig_exc = PyObject_Repr(value); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + PyErr_Format(PyExc_ImportError, + "could not import glib (error was: %s)", + _PyUnicode_AsString(py_orig_exc)); + Py_DECREF(py_orig_exc); + } else { + PyErr_SetString(PyExc_ImportError, + "could not import glib (no error given)"); + } + return; + } + + cobject = PyObject_GetAttrString(glib, "_PyGLib_API"); + if (cobject && PyCObject_Check(cobject)) + _PyGLib_API = (struct _PyGLib_Functions *) PyCObject_AsVoidPtr(cobject); + else { + PyErr_SetString(PyExc_ImportError, + "could not import glib (could not find _PyGLib_API object)"); + Py_DECREF(glib); + return; + } + + _PyGMainContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "MainContext"); + _PyGOptionGroup_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionGroup"); + _PyGOptionContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionContext"); +} + +void +pyglib_init_internal(PyObject *api) +{ + _PyGLib_API = (struct _PyGLib_Functions *) PyCObject_AsVoidPtr(api); +} + +gboolean +pyglib_threads_enabled(void) +{ + g_return_val_if_fail (_PyGLib_API != NULL, FALSE); + + return _PyGLib_API->threads_enabled; +} + +PyGILState_STATE +pyglib_gil_state_ensure(void) +{ + g_return_val_if_fail (_PyGLib_API != NULL, PyGILState_LOCKED); + + if (!_PyGLib_API->threads_enabled) + return PyGILState_LOCKED; + + return PyGILState_Ensure(); +} + +void +pyglib_gil_state_release(PyGILState_STATE state) +{ + g_return_if_fail (_PyGLib_API != NULL); + + if (!_PyGLib_API->threads_enabled) + return; + + PyGILState_Release(state); +} + +/** + * pyglib_enable_threads: + * + * Returns: TRUE if threading is enabled, FALSE otherwise. + * + */ +#ifdef DISABLE_THREADING +gboolean +pyglib_enable_threads(void) +{ + PyErr_SetString(PyExc_RuntimeError, + "pyglib threading disabled at compile time"); + return FALSE; +} + +void +_pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback) +{ + /* Ignore, threads cannot be enabled. */ +} + +#else + +static GSList *thread_enabling_callbacks = NULL; + +/* Enable threading; note that the GIL must be held by the current + * thread when this function is called + */ +gboolean +pyglib_enable_threads(void) +{ + GSList *callback; + + g_return_val_if_fail (_PyGLib_API != NULL, FALSE); + + if (_PyGLib_API->threads_enabled) + return TRUE; + + PyEval_InitThreads(); + if (!g_threads_got_initialized) + g_thread_init(NULL); + + _PyGLib_API->threads_enabled = TRUE; + pyglib_thread_state_tls_key = PyThread_create_key(); + + for (callback = thread_enabling_callbacks; callback; callback = callback->next) + ((PyGLibThreadsEnabledFunc) callback->data) (); + + g_slist_free(thread_enabling_callbacks); + return TRUE; +} + +void +_pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback) +{ + if (callback && !pyglib_threads_enabled()) + thread_enabling_callbacks = g_slist_append(thread_enabling_callbacks, callback); +} +#endif + +int +pyglib_gil_state_ensure_py23 (void) +{ + return PyGILState_Ensure(); +} + +void +pyglib_gil_state_release_py23 (int flag) +{ + PyGILState_Release(flag); +} + +/** + * pyglib_block_threads: + * + */ +void +pyglib_block_threads(void) +{ + g_return_if_fail (_PyGLib_API != NULL); + + if (_PyGLib_API->block_threads != NULL) + (* _PyGLib_API->block_threads)(); +} + +/** + * pyglib_unblock_threads: + * + */ +void +pyglib_unblock_threads(void) +{ + g_return_if_fail (_PyGLib_API != NULL); + if (_PyGLib_API->unblock_threads != NULL) + (* _PyGLib_API->unblock_threads)(); +} + +/** + * pyglib_set_thread_block_funcs: + * + * hooks to register handlers for getting GDK threads to cooperate + * with python threading + */ +void +pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func, + PyGLibThreadBlockFunc unblock_threads_func) +{ + g_return_if_fail (_PyGLib_API != NULL); + + _PyGLib_API->block_threads = block_threads_func; + _PyGLib_API->unblock_threads = unblock_threads_func; +} + + +/** + * pyglib_error_check: + * @error: a pointer to the GError. + * + * Checks to see if the GError has been set. If the error has been + * set, then the glib.GError Python exception will be raised, and + * the GError cleared. + * + * Returns: True if an error was set. + */ +gboolean +pyglib_error_check(GError **error) +{ + PyGILState_STATE state; + PyObject *exc_type; + PyObject *exc_instance; + PyObject *d; + + g_return_val_if_fail(error != NULL, FALSE); + + if (*error == NULL) + return FALSE; + + state = pyglib_gil_state_ensure(); + + exc_type = _PyGLib_API->gerror_exception; + if (exception_table != NULL) + { + PyObject *item; + item = PyDict_GetItem(exception_table, _PyLong_FromLong((*error)->domain)); + if (item != NULL) + exc_type = item; + } + + exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message); + + if ((*error)->domain) { + PyObject_SetAttrString(exc_instance, "domain", + d=_PyUnicode_FromString(g_quark_to_string((*error)->domain))); + Py_DECREF(d); + } + else + PyObject_SetAttrString(exc_instance, "domain", Py_None); + + PyObject_SetAttrString(exc_instance, "code", + d=_PyLong_FromLong((*error)->code)); + Py_DECREF(d); + + if ((*error)->message) { + PyObject_SetAttrString(exc_instance, "message", + d=_PyUnicode_FromString((*error)->message)); + Py_DECREF(d); + } else { + PyObject_SetAttrString(exc_instance, "message", Py_None); + } + + PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance); + Py_DECREF(exc_instance); + g_clear_error(error); + + pyglib_gil_state_release(state); + + return TRUE; +} + +/** + * pyglib_gerror_exception_check: + * @error: a standard GLib GError ** output parameter + * + * Checks to see if a GError exception has been raised, and if so + * translates the python exception to a standard GLib GError. If the + * raised exception is not a GError then PyErr_Print() is called. + * + * Returns: 0 if no exception has been raised, -1 if it is a + * valid glib.GError, -2 otherwise. + */ +gboolean +pyglib_gerror_exception_check(GError **error) +{ + PyObject *type, *value, *traceback; + PyObject *py_message, *py_domain, *py_code; + const char *bad_gerror_message; + + PyErr_Fetch(&type, &value, &traceback); + if (type == NULL) + return 0; + PyErr_NormalizeException(&type, &value, &traceback); + if (value == NULL) { + PyErr_Restore(type, value, traceback); + PyErr_Print(); + return -2; + } + if (!value || + !PyErr_GivenExceptionMatches(type, + (PyObject *) _PyGLib_API->gerror_exception)) { + PyErr_Restore(type, value, traceback); + PyErr_Print(); + return -2; + } + Py_DECREF(type); + Py_XDECREF(traceback); + + py_message = PyObject_GetAttrString(value, "message"); + if (!py_message || !_PyUnicode_Check(py_message)) { + bad_gerror_message = "glib.GError instances must have a 'message' string attribute"; + goto bad_gerror; + } + + py_domain = PyObject_GetAttrString(value, "domain"); + if (!py_domain || !_PyUnicode_Check(py_domain)) { + bad_gerror_message = "glib.GError instances must have a 'domain' string attribute"; + Py_DECREF(py_message); + goto bad_gerror; + } + + py_code = PyObject_GetAttrString(value, "code"); + if (!py_code || !_PyLong_Check(py_code)) { + bad_gerror_message = "glib.GError instances must have a 'code' int attribute"; + Py_DECREF(py_message); + Py_DECREF(py_domain); + goto bad_gerror; + } + + g_set_error(error, g_quark_from_string(_PyUnicode_AsString(py_domain)), + _PyLong_AsLong(py_code), _PyUnicode_AsString(py_message)); + + Py_DECREF(py_message); + Py_DECREF(py_code); + Py_DECREF(py_domain); + return -1; + +bad_gerror: + Py_DECREF(value); + g_set_error(error, g_quark_from_static_string("pyglib"), 0, bad_gerror_message); + PyErr_SetString(PyExc_ValueError, bad_gerror_message); + PyErr_Print(); + return -2; +} + +/** + * pyglib_register_exception_for_domain: + * @name: name of the exception + * @error_domain: error domain + * + * Registers a new glib.GError exception subclass called #name for + * a specific #domain. This exception will be raised when a GError + * of the same domain is passed in to pyglib_error_check(). + * + * Returns: the new exception + */ +PyObject * +pyglib_register_exception_for_domain(gchar *name, + gint error_domain) +{ + PyObject *exception; + + exception = PyErr_NewException(name, _PyGLib_API->gerror_exception, NULL); + + if (exception_table == NULL) + exception_table = PyDict_New(); + + PyDict_SetItem(exception_table, + _PyLong_FromLong(error_domain), + exception); + + return exception; +} + +/** + * pyglib_main_context_new: + * @context: a GMainContext. + * + * Creates a wrapper for a GMainContext. + * + * Returns: the GMainContext wrapper. + */ +PyObject * +pyglib_main_context_new(GMainContext *context) +{ + PyGMainContext *self; + + self = (PyGMainContext *)PyObject_NEW(PyGMainContext, + &PyGMainContext_Type); + if (self == NULL) + return NULL; + + self->context = g_main_context_ref(context); + return (PyObject *)self; +} + +/** + * pyg_option_group_transfer_group: + * @group: a GOptionGroup wrapper + * + * This is used to transfer the GOptionGroup to a GOptionContext. After this + * is called, the calle must handle the release of the GOptionGroup. + * + * When #NULL is returned, the GOptionGroup was already transfered. + * + * Returns: Either #NULL or the wrapped GOptionGroup. + */ +GOptionGroup * +pyglib_option_group_transfer_group(PyObject *obj) +{ + PyGOptionGroup *self = (PyGOptionGroup*)obj; + + if (self->is_in_context) + return NULL; + + self->is_in_context = TRUE; + + /* Here we increase the reference count of the PyGOptionGroup, because now + * the GOptionContext holds an reference to us (it is the userdata passed + * to g_option_group_new(). + * + * The GOptionGroup is freed with the GOptionContext. + * + * We set it here because if we would do this in the init method we would + * hold two references and the PyGOptionGroup would never be freed. + */ + Py_INCREF(self); + + return self->group; +} + +/** + * pyglib_option_group_new: + * @group: a GOptionGroup + * + * The returned GOptionGroup can't be used to set any hooks, translation domains + * or add entries. It's only intend is, to use for GOptionContext.add_group(). + * + * Returns: the GOptionGroup wrapper. + */ +PyObject * +pyglib_option_group_new (GOptionGroup *group) +{ + PyGOptionGroup *self; + + self = (PyGOptionGroup *)PyObject_NEW(PyGOptionGroup, + &PyGOptionGroup_Type); + if (self == NULL) + return NULL; + + self->group = group; + self->other_owner = TRUE; + self->is_in_context = FALSE; + + return (PyObject *)self; +} + +/** + * pyglib_option_context_new: + * @context: a GOptionContext + * + * Returns: A new GOptionContext wrapper. + */ +PyObject * +pyglib_option_context_new (GOptionContext *context) +{ + PyGOptionContext *self; + + self = (PyGOptionContext *)PyObject_NEW(PyGOptionContext, + &PyGOptionContext_Type); + if (self == NULL) + return NULL; + + self->context = context; + self->main_group = NULL; + + return (PyObject *)self; +} + +/** + * pyglib_option_context_new: + * @context: a GTimeVal struct + * + * Converts a GTimeVal struct to a python float + * + * Returns: a float representing the timeval + */ +PyObject * +pyglib_float_from_timeval(GTimeVal timeval) +{ + double ret; + ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001; + return PyFloat_FromDouble(ret); +} + + +/****** Private *****/ + +/** + * _pyglib_destroy_notify: + * @user_data: a PyObject pointer. + * + * A function that can be used as a GDestroyNotify callback that will + * call Py_DECREF on the data. + */ +void +_pyglib_destroy_notify(gpointer user_data) +{ + PyObject *obj = (PyObject *)user_data; + PyGILState_STATE state; + + g_return_if_fail (_PyGLib_API != NULL); + + state = pyglib_gil_state_ensure(); + Py_DECREF(obj); + pyglib_gil_state_release(state); +} + +gboolean +_pyglib_handler_marshal(gpointer user_data) +{ + PyObject *tuple, *ret; + gboolean res; + PyGILState_STATE state; + + g_return_val_if_fail(user_data != NULL, FALSE); + + state = pyglib_gil_state_ensure(); + + tuple = (PyObject *)user_data; + ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0), + PyTuple_GetItem(tuple, 1)); + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + pyglib_gil_state_release(state); + + return res; +} + + diff --git a/glib/pyglib.h b/glib/pyglib.h new file mode 100644 index 0000000..84bb36c --- /dev/null +++ b/glib/pyglib.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGLIB_H__ +#define __PYGLIB_H__ + +#include <Python.h> + +#include <glib.h> + +G_BEGIN_DECLS + +typedef void (*PyGLibThreadsEnabledFunc) (void); +typedef void (*PyGLibThreadBlockFunc) (void); + +void pyglib_init(void); +void pyglib_init_internal(PyObject *api); +PyGILState_STATE pyglib_gil_state_ensure(void); +void pyglib_gil_state_release(PyGILState_STATE state); +int pyglib_enable_threads(void); +gboolean pyglib_error_check(GError **error); +gboolean pyglib_gerror_exception_check(GError **error); +PyObject *pyglib_register_exception_for_domain(gchar *name, + gint error_domain); +gboolean pyglib_threads_enabled(void); +PyObject * pyglib_main_context_new(GMainContext *context); +void pyglib_set_thread_block_funcs(PyGLibThreadBlockFunc block_threads_func, + PyGLibThreadBlockFunc unblock_threads_func); +void pyglib_block_threads(void); +void pyglib_unblock_threads(void); +PyObject * pyglib_option_context_new(GOptionContext *context); +PyObject * pyglib_option_group_new(GOptionGroup *group); +GOptionGroup * pyglib_option_group_transfer_group(PyObject *self); +PyObject * pyglib_float_from_timeval(GTimeVal timeval); + +/* Private: for gobject <-> glib interaction only. */ +void _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback); + +#define pyglib_begin_allow_threads \ + G_STMT_START { \ + PyThreadState *_save = NULL; \ + if (pyglib_threads_enabled()) \ + _save = PyEval_SaveThread(); + +#define pyglib_end_allow_threads \ + if (pyglib_threads_enabled()) \ + PyEval_RestoreThread(_save); \ + } G_STMT_END + +#define PYGLIB_MODULE_START(symbol, modname) \ +DL_EXPORT(void) init##symbol(void) \ +{ \ + PyObject *module; \ + module = Py_InitModule(modname, symbol##_functions); +#define PYGLIB_MODULE_END } +#define PYGLIB_DEFINE_TYPE(typename, symbol, csymbol) \ +PyTypeObject symbol = { \ + PyObject_HEAD_INIT(NULL) \ + 0, \ + typename, \ + sizeof(csymbol), \ + 0, \ +}; +#define PYGLIB_REGISTER_TYPE(d, type, name) \ + if (!type.tp_alloc) \ + type.tp_alloc = PyType_GenericAlloc; \ + if (!type.tp_new) \ + type.tp_new = PyType_GenericNew; \ + if (PyType_Ready(&type)) \ + return; \ + PyDict_SetItemString(d, name, (PyObject *)&type); + +G_END_DECLS + +#endif /* __PYGLIB_H__ */ + diff --git a/glib/pygmaincontext.c b/glib/pygmaincontext.c new file mode 100644 index 0000000..186215a --- /dev/null +++ b/glib/pygmaincontext.c @@ -0,0 +1,99 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygtk- Python bindings for the GTK toolkit. + * Copyright (C) 1998-2003 James Henstridge + * + * pygmaincontext.c: GMainContext wrapper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <Python.h> +#include <pythread.h> +#include <glib.h> +#include "pygmaincontext.h" +#include "pyglib.h" +#include "pyglib-private.h" + +PYGLIB_DEFINE_TYPE("glib.MainContext", PyGMainContext_Type, PyGMainContext) + +static int +pyg_main_context_init(PyGMainContext *self) +{ + self->context = g_main_context_new(); + return 0; +} + +static void +pyg_main_context_dealloc(PyGMainContext *self) +{ + if (self->context != NULL) { + g_main_context_unref(self->context); + self->context = NULL; + } + + PyObject_Del(self); +} + +static int +pyg_main_context_compare(PyGMainContext *self, PyGMainContext *v) +{ + if (self->context == v->context) return 0; + if (self->context > v->context) return -1; + return 1; +} + +static PyObject * +_wrap_g_main_context_iteration (PyGMainContext *self, PyObject *args) +{ + gboolean ret, may_block = TRUE; + + if (!PyArg_ParseTuple(args, "|i:GMainContext.iteration", + &may_block)) + return NULL; + + pyglib_begin_allow_threads; + ret = g_main_context_iteration(self->context, may_block); + pyglib_end_allow_threads; + + return PyBool_FromLong(ret); +} + +static PyObject * +_wrap_g_main_context_pending (PyGMainContext *self) +{ + return PyBool_FromLong(g_main_context_pending(self->context)); +} + +static PyMethodDef _PyGMainContext_methods[] = { + { "iteration", (PyCFunction)_wrap_g_main_context_iteration, METH_VARARGS }, + { "pending", (PyCFunction)_wrap_g_main_context_pending, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +void +pyglib_maincontext_register_types(PyObject *d) +{ + PyGMainContext_Type.tp_dealloc = (destructor)pyg_main_context_dealloc; + PyGMainContext_Type.tp_compare = (cmpfunc)pyg_main_context_compare; + PyGMainContext_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + PyGMainContext_Type.tp_methods = _PyGMainContext_methods; + PyGMainContext_Type.tp_init = (initproc)pyg_main_context_init; + PYGLIB_REGISTER_TYPE(d, PyGMainContext_Type, "MainContext"); +} diff --git a/glib/pygmaincontext.h b/glib/pygmaincontext.h new file mode 100644 index 0000000..038cb37 --- /dev/null +++ b/glib/pygmaincontext.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_MAINCONTEXT_H__ +#define __PYG_MAINCONTEXT_H__ + +#include <Python.h> +#include <glib.h> + +typedef struct { + PyObject_HEAD + GMainContext *context; +} PyGMainContext; + +extern PyTypeObject PyGMainContext_Type; + +PyObject * pyglib_main_context_new(GMainContext *context); + +void pyglib_maincontext_register_types(PyObject *d); + +#endif /* __PYG_MAINCONTEXT_H__ */ + diff --git a/glib/pygmainloop.c b/glib/pygmainloop.c new file mode 100644 index 0000000..d9f048c --- /dev/null +++ b/glib/pygmainloop.c @@ -0,0 +1,354 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygtk- Python bindings for the GTK toolkit. + * Copyright (C) 1998-2003 James Henstridge + * Copyright (C) 2004 Johan Dahlin + * + * pygmainloop.c: GMainLoop wrapper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <fcntl.h> + +#include <Python.h> +#include <pythread.h> +#include <glib.h> + +#include "pygmainloop.h" +#include "pygmaincontext.h" +#include "pyglib.h" +#include "pyglib-private.h" + +static int pipe_fds[2]; + +typedef struct { + GSource source; + GPollFD fd; +} PySignalWatchSource; + +#ifdef DISABLE_THREADING +static GMainLoop *pyg_current_main_loop = NULL;; + +static inline GMainLoop * +pyg_save_current_main_loop (GMainLoop *main_loop) +{ + GMainLoop *retval = pyg_current_main_loop; + + g_return_val_if_fail(main_loop != NULL, NULL); + + pyg_current_main_loop = g_main_loop_ref(main_loop); + + return retval; +} + +static inline void +pyg_restore_current_main_loop (GMainLoop *main_loop) +{ + if (pyg_current_main_loop != NULL) + g_main_loop_unref(pyg_current_main_loop); + pyg_current_main_loop = main_loop; +} + +static inline GMainLoop * +pyg_get_current_main_loop (void) +{ + return pyg_current_main_loop; +} +#else /* !defined(#ifndef DISABLE_THREADING) */ + +static int pyg_current_main_loop_key = -1; + +static inline GMainLoop * +pyg_save_current_main_loop (GMainLoop *main_loop) +{ + GMainLoop *retval; + + g_return_val_if_fail(main_loop != NULL, NULL); + + if (pyg_current_main_loop_key == -1) + pyg_current_main_loop_key = PyThread_create_key(); + + retval = PyThread_get_key_value(pyg_current_main_loop_key); + PyThread_delete_key_value(pyg_current_main_loop_key); + PyThread_set_key_value(pyg_current_main_loop_key, + g_main_loop_ref(main_loop)); + + return retval; +} + +static inline void +pyg_restore_current_main_loop (GMainLoop *main_loop) +{ + GMainLoop *prev; + + g_return_if_fail (pyg_current_main_loop_key != -1); + + prev = PyThread_get_key_value(pyg_current_main_loop_key); + if (prev != NULL) + g_main_loop_unref(prev); + PyThread_delete_key_value(pyg_current_main_loop_key); + if (main_loop != NULL) + PyThread_set_key_value(pyg_current_main_loop_key, main_loop); +} + +static inline GMainLoop * +pyg_get_current_main_loop (void) +{ + if (pyg_current_main_loop_key == -1) + return NULL; + return PyThread_get_key_value(pyg_current_main_loop_key); +} +#endif /* DISABLE_THREADING */ + +static gboolean +pyg_signal_watch_prepare(GSource *source, + int *timeout) +{ + /* Python only invokes signal handlers from the main thread, + * so if a thread other than the main thread receives the signal + * from the kernel, PyErr_CheckSignals() from that thread will + * do nothing. + */ + +#ifdef HAVE_PYSIGNAL_SETWAKEUPFD + return FALSE; +#else /* !HAVE_PYSIGNAL_SETWAKEUPFD */ + /* On Windows g_poll() won't be interrupted by a signal + * (AFAIK), so we need the timeout there too, even if there's + * only one thread. + */ +#ifndef PLATFORM_WIN32 + if (!pyglib_threads_enabled()) + return FALSE; +#endif /* PLATFORM_WIN32 */ + + /* If we're using 2.5 or an earlier version of python we + * will default to a timeout every second, be aware, + * this will cause unnecessary wakeups, see + * http://bugzilla.gnome.org/show_bug.cgi?id=481569 + */ + *timeout = 1000; + return FALSE; +#endif /* HAVE_PYSIGNAL_SETWAKEUPFD */ +} + +static gboolean +pyg_signal_watch_check(GSource *source) +{ + PyGILState_STATE state; + GMainLoop *main_loop; + +#ifdef HAVE_PYSIGNAL_SETWAKEUPFD + PySignalWatchSource *real_source = (PySignalWatchSource *)source; + GPollFD *poll_fd = &real_source->fd; + unsigned char dummy; + if (poll_fd->revents & G_IO_IN) + read(poll_fd->fd, &dummy, 1); +#endif + + state = pyglib_gil_state_ensure(); + + main_loop = pyg_get_current_main_loop(); + + if (PyErr_CheckSignals() == -1 && main_loop != NULL) { + PyErr_SetNone(PyExc_KeyboardInterrupt); + g_main_loop_quit(main_loop); + } + + pyglib_gil_state_release(state); + + return FALSE; +} + +static gboolean +pyg_signal_watch_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + /* We should never be dispatched */ + g_assert_not_reached(); + return TRUE; +} + +static GSourceFuncs pyg_signal_watch_funcs = +{ + pyg_signal_watch_prepare, + pyg_signal_watch_check, + pyg_signal_watch_dispatch +}; + +static GSource * +pyg_signal_watch_new(void) +{ + GSource *source = g_source_new(&pyg_signal_watch_funcs, + sizeof(PySignalWatchSource)); + +#ifdef HAVE_PYSIGNAL_SETWAKEUPFD + PySignalWatchSource *real_source = (PySignalWatchSource *)source; + int flag; + + /* Unfortunately we need to create a new pipe here instead of + * reusing the pipe inside the GMainContext. + * Ideally an api should be added to GMainContext which allows us + * to reuse that pipe which would suit us perfectly fine. + * XXX More efficient than a pipe, we could use an eventfd on Linux + * kernels that support it. + */ + gint already_piped = (pipe_fds[0] > 0); + if (!already_piped) { + if (pipe(pipe_fds) < 0) + g_error("Cannot create main loop pipe: %s\n", + g_strerror(errno)); + + /* Make the write end of the fd non blocking */ + flag = fcntl(pipe_fds[1], F_GETFL, 0); + flag |= O_NONBLOCK; + fcntl(pipe_fds[1], F_SETFL, flag); + } + + real_source->fd.fd = pipe_fds[0]; + real_source->fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + g_source_add_poll(source, &real_source->fd); + + if (!already_piped) + PySignal_SetWakeupFd(pipe_fds[1]); +#endif + return source; +} + +PYGLIB_DEFINE_TYPE("glib.MainLoop", PyGMainLoop_Type, PyGMainLoop) + +static int +pyg_main_loop_init(PyGMainLoop *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "context", "is_running", NULL }; + PyObject *py_context = Py_None; + int is_running = 0; + GMainContext *context; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|Ob:GMainLoop.__init__", + kwlist, &py_context, &is_running)) + return -1; + + if (!PyObject_TypeCheck(py_context, &PyGMainContext_Type) && + py_context != Py_None) { + PyErr_SetString(PyExc_TypeError, + "context must be a glib.MainContext or None"); + return -1; + } + + if (py_context != Py_None) { + context = ((PyGMainContext*)py_context)->context; + } else { + context = NULL; + } + + self->loop = g_main_loop_new(context, is_running); + + self->signal_source = pyg_signal_watch_new(); + g_source_attach(self->signal_source, context); + g_source_unref(self->signal_source); + + return 0; +} + +static void +pyg_main_loop_dealloc(PyGMainLoop *self) +{ + if (self->signal_source != NULL) { + g_source_destroy(self->signal_source); + self->signal_source = NULL; + } + + if (self->loop != NULL) { + g_main_loop_unref(self->loop); + self->loop = NULL; + } + + PyObject_Del(self); +} + +static int +pyg_main_loop_compare(PyGMainLoop *self, PyGMainLoop *v) +{ + if (self->loop == v->loop) return 0; + if (self->loop > v->loop) return -1; + return 1; +} + +static PyObject * +_wrap_g_main_loop_get_context (PyGMainLoop *loop) +{ + return pyglib_main_context_new(g_main_loop_get_context(loop->loop)); +} + +static PyObject * +_wrap_g_main_loop_is_running (PyGMainLoop *self) +{ + return PyBool_FromLong(g_main_loop_is_running(self->loop)); +} + +static PyObject * +_wrap_g_main_loop_quit (PyGMainLoop *self) +{ + g_main_loop_quit(self->loop); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +_wrap_g_main_loop_run (PyGMainLoop *self) +{ + GMainLoop *prev_loop; + + prev_loop = pyg_save_current_main_loop(self->loop); + + pyglib_begin_allow_threads; + g_main_loop_run(self->loop); + pyglib_end_allow_threads; + + pyg_restore_current_main_loop(prev_loop); + + if (PyErr_Occurred()) + return NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef _PyGMainLoop_methods[] = { + { "get_context", (PyCFunction)_wrap_g_main_loop_get_context, METH_NOARGS }, + { "is_running", (PyCFunction)_wrap_g_main_loop_is_running, METH_NOARGS }, + { "quit", (PyCFunction)_wrap_g_main_loop_quit, METH_NOARGS }, + { "run", (PyCFunction)_wrap_g_main_loop_run, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +void +pyglib_mainloop_register_types(PyObject *d) +{ + PyGMainLoop_Type.tp_dealloc = (destructor)pyg_main_loop_dealloc; + PyGMainLoop_Type.tp_compare = (cmpfunc)pyg_main_loop_compare; + PyGMainLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + PyGMainLoop_Type.tp_methods = _PyGMainLoop_methods; + PyGMainLoop_Type.tp_init = (initproc)pyg_main_loop_init; + PYGLIB_REGISTER_TYPE(d, PyGMainLoop_Type, "MainLoop"); +} diff --git a/glib/pygmainloop.h b/glib/pygmainloop.h new file mode 100644 index 0000000..dec82d8 --- /dev/null +++ b/glib/pygmainloop.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_MAINLOOP_H__ +#define __PYG_MAINLOOP_H__ + +typedef struct { + PyObject_HEAD + GMainLoop *loop; + GSource *signal_source; +} PyGMainLoop; + +extern PyTypeObject PyGMainLoop_Type; + +void pyglib_mainloop_register_types(PyObject *d); + +#endif /* __PYG_MAINLOOP_H__ */ + diff --git a/glib/pygoptioncontext.c b/glib/pygoptioncontext.c new file mode 100644 index 0000000..92ba901 --- /dev/null +++ b/glib/pygoptioncontext.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygtk- Python bindings for the GTK toolkit. + * Copyright (C) 2006 Johannes Hoelzl + * + * pygoptioncontext.c: GOptionContext wrapper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <pyglib.h> +#include "pyglib-private.h" +#include "pygoptioncontext.h" + +PYGLIB_DEFINE_TYPE("glib.OptionContext", PyGOptionContext_Type, PyGOptionContext) + +static int +pyg_option_context_init(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + char *parameter_string; + + if (!PyArg_ParseTuple(args, "s:glib.GOptionContext.__init__", + ¶meter_string)) + return -1; + + self->context = g_option_context_new(parameter_string); + return 0; +} + +static void +pyg_option_context_dealloc(PyGOptionContext *self) +{ + Py_CLEAR(self->main_group); + + if (self->context != NULL) + { + GOptionContext *tmp = self->context; + self->context = NULL; + g_option_context_free(tmp); + } + + PyObject_Del(self); +} + +static PyObject * +pyg_option_context_parse(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "argv", NULL }; + PyObject *arg; + PyObject *new_argv, *argv; + Py_ssize_t argv_length, pos; + gint argv_length_int; + char **argv_content, **original; + GError *error = NULL; + gboolean result; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GOptionContext.parse", + kwlist, &argv)) + return NULL; + + if (!PyList_Check(argv)) + { + PyErr_SetString(PyExc_TypeError, + "GOptionContext.parse expects a list of strings."); + return NULL; + } + + argv_length = PyList_Size(argv); + if (argv_length == -1) + { + PyErr_SetString(PyExc_TypeError, + "GOptionContext.parse expects a list of strings."); + return NULL; + } + + argv_content = g_new(char*, argv_length + 1); + argv_content[argv_length] = NULL; + for (pos = 0; pos < argv_length; pos++) + { + arg = PyList_GetItem(argv, pos); + argv_content[pos] = g_strdup(_PyUnicode_AsString(arg)); + if (argv_content[pos] == NULL) + { + g_strfreev(argv_content); + return NULL; + } + } + original = g_strdupv(argv_content); + + g_assert(argv_length <= G_MAXINT); + argv_length_int = argv_length; + pyglib_begin_allow_threads; + result = g_option_context_parse(self->context, &argv_length_int, &argv_content, + &error); + pyglib_end_allow_threads; + argv_length = argv_length_int; + + if (!result) + { + g_strfreev(argv_content); + g_strfreev(original); + pyglib_error_check(&error); + return NULL; + } + + new_argv = PyList_New(g_strv_length(argv_content)); + for (pos = 0; pos < argv_length; pos++) + { + arg = _PyUnicode_FromString(argv_content[pos]); + PyList_SetItem(new_argv, pos, arg); + } + + g_strfreev(original); + g_strfreev(argv_content); + return new_argv; +} + +static PyObject * +pyg_option_context_set_help_enabled(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "help_enable", NULL }; + + PyObject *help_enabled; + if (! PyArg_ParseTupleAndKeywords(args, kwargs, + "O:GOptionContext.set_help_enabled", + kwlist, &help_enabled)) + return NULL; + + g_option_context_set_help_enabled(self->context, PyObject_IsTrue(help_enabled)); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_option_context_get_help_enabled(PyGOptionContext *self) +{ + return PyBool_FromLong(g_option_context_get_help_enabled(self->context)); +} + +static PyObject * +pyg_option_context_set_ignore_unknown_options(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "ignore_unknown_options", NULL }; + PyObject *ignore_unknown_options; + + if (! PyArg_ParseTupleAndKeywords(args, kwargs, + "O:GOptionContext.set_ignore_unknown_options", + kwlist, &ignore_unknown_options)) + return NULL; + + g_option_context_set_ignore_unknown_options(self->context, + PyObject_IsTrue(ignore_unknown_options)); + + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_option_context_get_ignore_unknown_options(PyGOptionContext *self) +{ + return PyBool_FromLong( + g_option_context_get_ignore_unknown_options(self->context)); +} + +static PyObject * +pyg_option_context_set_main_group(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "group", NULL }; + GOptionGroup *g_group; + PyObject *group; + + if (! PyArg_ParseTupleAndKeywords(args, kwargs, + "O:GOptionContext.set_main_group", + kwlist, &group)) + return NULL; + + if (PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) { + PyErr_SetString(PyExc_TypeError, + "GOptionContext.set_main_group expects a GOptionGroup."); + return NULL; + } + + g_group = pyglib_option_group_transfer_group(group); + if (g_group == NULL) + { + PyErr_SetString(PyExc_RuntimeError, + "Group is already in a OptionContext."); + return NULL; + } + + g_option_context_set_main_group(self->context, g_group); + + Py_INCREF(group); + self->main_group = (PyGOptionGroup*) group; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_option_context_get_main_group(PyGOptionContext *self) +{ + if (self->main_group == NULL) + { + Py_INCREF(Py_None); + return Py_None; + } + Py_INCREF(self->main_group); + return (PyObject*) self->main_group; +} + +static PyObject * +pyg_option_context_add_group(PyGOptionContext *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "group", NULL }; + GOptionGroup *g_group; + PyObject *group; + + if (! PyArg_ParseTupleAndKeywords(args, kwargs, + "O:GOptionContext.add_group", + kwlist, &group)) + return NULL; + + if (PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) { + PyErr_SetString(PyExc_TypeError, + "GOptionContext.add_group expects a GOptionGroup."); + return NULL; + } + + g_group = pyglib_option_group_transfer_group(group); + if (g_group == NULL) + { + PyErr_SetString(PyExc_RuntimeError, + "Group is already in a OptionContext."); + return NULL; + } + Py_INCREF(group); + + g_option_context_add_group(self->context, g_group); + + Py_INCREF(Py_None); + return Py_None; +} + +static int +pyg_option_context_compare(PyGOptionContext *self, PyGOptionContext *context) +{ + if (self->context == context->context) return 0; + if (self->context > context->context) + return 1; + return -1; +} + +static PyObject * +pyg_option_get_context(PyGOptionContext *self) +{ + return PyCObject_FromVoidPtr(self->context, NULL); +} + +static PyMethodDef pyg_option_context_methods[] = { + { "parse", (PyCFunction)pyg_option_context_parse, METH_VARARGS | METH_KEYWORDS }, + { "set_help_enabled", (PyCFunction)pyg_option_context_set_help_enabled, METH_VARARGS | METH_KEYWORDS }, + { "get_help_enabled", (PyCFunction)pyg_option_context_get_help_enabled, METH_NOARGS }, + { "set_ignore_unknown_options", (PyCFunction)pyg_option_context_set_ignore_unknown_options, METH_VARARGS | METH_KEYWORDS }, + { "get_ignore_unknown_options", (PyCFunction)pyg_option_context_get_ignore_unknown_options, METH_NOARGS }, + { "set_main_group", (PyCFunction)pyg_option_context_set_main_group, METH_VARARGS | METH_KEYWORDS }, + { "get_main_group", (PyCFunction)pyg_option_context_get_main_group, METH_NOARGS }, + { "add_group", (PyCFunction)pyg_option_context_add_group, METH_VARARGS | METH_KEYWORDS }, + { "_get_context", (PyCFunction)pyg_option_get_context, METH_NOARGS }, + { NULL, NULL, 0 }, +}; + +void +pyglib_option_context_register_types(PyObject *d) +{ + PyGOptionContext_Type.tp_dealloc = (destructor)pyg_option_context_dealloc; + PyGOptionContext_Type.tp_compare = (cmpfunc)pyg_option_context_compare; + PyGOptionContext_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyGOptionContext_Type.tp_methods = pyg_option_context_methods; + PyGOptionContext_Type.tp_init = (initproc)pyg_option_context_init; + PYGLIB_REGISTER_TYPE(d, PyGOptionContext_Type, "OptionContext"); +} diff --git a/glib/pygoptioncontext.h b/glib/pygoptioncontext.h new file mode 100644 index 0000000..85d0a47 --- /dev/null +++ b/glib/pygoptioncontext.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_OPTIONCONTEXT_H__ +#define __PYG_OPTIONCONTEXT_H__ + +#include "pygoptiongroup.h" + +extern PyTypeObject PyGOptionContext_Type; + +typedef struct { + PyObject_HEAD + PyGOptionGroup *main_group; + GOptionContext *context; +} PyGOptionContext; + +void pyglib_option_context_register_types(PyObject *d); + +#endif /* __PYG_OPTIONCONTEXT_H__ */ diff --git a/glib/pygoptiongroup.c b/glib/pygoptiongroup.c new file mode 100644 index 0000000..70e4529 --- /dev/null +++ b/glib/pygoptiongroup.c @@ -0,0 +1,270 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygobject - Python bindings for the GLib, GObject and GIO + * Copyright (C) 2006 Johannes Hoelzl + * + * pygoptiongroup.c: GOptionContext and GOptionGroup wrapper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <pyglib.h> +#include "pyglib-private.h" +#include "pygoptiongroup.h" + +PYGLIB_DEFINE_TYPE("glib.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup) + +static gboolean +check_if_owned(PyGOptionGroup *self) +{ + if (self->other_owner) + { + PyErr_SetString(PyExc_ValueError, "The GOptionGroup was not created by " + "glib.OptionGroup(), so operation is not possible."); + return TRUE; + } + return FALSE; +} + +static void +destroy_g_group(PyGOptionGroup *self) +{ + PyGILState_STATE state; + state = pyglib_gil_state_ensure(); + + self->group = NULL; + Py_CLEAR(self->callback); + g_slist_foreach(self->strings, (GFunc) g_free, NULL); + g_slist_free(self->strings); + self->strings = NULL; + + if (self->is_in_context) + { + Py_DECREF(self); + } + + pyglib_gil_state_release(state); +} + +static int +pyg_option_group_init(PyGOptionGroup *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "name", "description", "help_description", + "callback", NULL }; + char *name, *description, *help_description; + PyObject *callback; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zzzO:GOptionGroup.__init__", + kwlist, &name, &description, + &help_description, &callback)) + return -1; + + self->group = g_option_group_new(name, description, help_description, + self, (GDestroyNotify) destroy_g_group); + self->other_owner = FALSE; + self->is_in_context = FALSE; + + Py_INCREF(callback); + self->callback = callback; + + return 0; +} + +static void +pyg_option_group_dealloc(PyGOptionGroup *self) +{ + if (!self->other_owner && !self->is_in_context) + { + GOptionGroup *tmp = self->group; + self->group = NULL; + if (tmp) + g_option_group_free(tmp); + } + + PyObject_Del(self); +} + +static gboolean +arg_func(const gchar *option_name, + const gchar *value, + PyGOptionGroup *self, + GError **error) +{ + PyObject *ret; + PyGILState_STATE state; + gboolean no_error; + + state = pyglib_gil_state_ensure(); + + if (value == NULL) + ret = PyObject_CallFunction(self->callback, "sOO", + option_name, Py_None, self); + else + ret = PyObject_CallFunction(self->callback, "ssO", + option_name, value, self); + + if (ret != NULL) + { + Py_DECREF(ret); + no_error = TRUE; + } else + no_error = pyglib_gerror_exception_check(error) != -1; + + pyglib_gil_state_release(state); + return no_error; +} + +static PyObject * +pyg_option_group_add_entries(PyGOptionGroup *self, PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "entries", NULL }; + gssize entry_count, pos; + PyObject *entry_tuple, *list; + GOptionEntry *entries; + + if (check_if_owned(self)) + return NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GOptionGroup.add_entries", + kwlist, &list)) + return NULL; + + if (!PyList_Check(list)) + { + PyErr_SetString(PyExc_TypeError, + "GOptionGroup.add_entries expected a list of entries"); + return NULL; + } + + entry_count = PyList_Size(list); + if (entry_count == -1) + { + PyErr_SetString(PyExc_TypeError, + "GOptionGroup.add_entries expected a list of entries"); + return NULL; + } + + entries = g_new0(GOptionEntry, entry_count + 1); + for (pos = 0; pos < entry_count; pos++) + { + gchar *long_name, *description, *arg_description; + entry_tuple = PyList_GetItem(list, pos); + if (!PyTuple_Check(entry_tuple)) + { + PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries " + "expected a list of entries"); + g_free(entries); + return NULL; + } + if (!PyArg_ParseTuple(entry_tuple, "scisz", + &long_name, + &(entries[pos].short_name), + &(entries[pos].flags), + &description, + &arg_description)) + { + PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries " + "expected a list of entries"); + g_free(entries); + return NULL; + } + long_name = g_strdup(long_name); + self->strings = g_slist_prepend(self->strings, long_name); + entries[pos].long_name = long_name; + + description = g_strdup(description); + self->strings = g_slist_prepend(self->strings, description); + entries[pos].description = description; + + arg_description = g_strdup(arg_description); + self->strings = g_slist_prepend(self->strings, arg_description); + entries[pos].arg_description = arg_description; + + entries[pos].arg = G_OPTION_ARG_CALLBACK; + entries[pos].arg_data = arg_func; + } + + g_option_group_add_entries(self->group, entries); + + g_free(entries); + + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +pyg_option_group_set_translation_domain(PyGOptionGroup *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "domain", NULL }; + char *domain; + + if (check_if_owned(self)) + return NULL; + + if (self->group == NULL) + { + PyErr_SetString(PyExc_RuntimeError, + "The corresponding GOptionGroup was already freed, " + "probably through the release of GOptionContext"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "z:GOptionGroup.set_translate_domain", + kwlist, &domain)) + return NULL; + + g_option_group_set_translation_domain(self->group, domain); + + Py_INCREF(Py_None); + return Py_None; +} + +static int +pyg_option_group_compare(PyGOptionGroup *self, PyGOptionGroup *group) +{ + if (self->group == group->group) + return 0; + + if (self->group > group->group) + return 1; + + return -1; +} + +static PyMethodDef pyg_option_group_methods[] = { + { "add_entries", (PyCFunction)pyg_option_group_add_entries, METH_VARARGS | METH_KEYWORDS }, + { "set_translation_domain", (PyCFunction)pyg_option_group_set_translation_domain, METH_VARARGS | METH_KEYWORDS }, + { NULL, NULL, 0 }, +}; + +void +pyglib_option_group_register_types(PyObject *d) +{ + PyGOptionGroup_Type.tp_dealloc = (destructor)pyg_option_group_dealloc; + PyGOptionGroup_Type.tp_compare = (cmpfunc)pyg_option_group_compare; + PyGOptionGroup_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + PyGOptionGroup_Type.tp_methods = pyg_option_group_methods; + PyGOptionGroup_Type.tp_init = (initproc)pyg_option_group_init; + PYGLIB_REGISTER_TYPE(d, PyGOptionGroup_Type, "OptionGroup"); +} diff --git a/glib/pygoptiongroup.h b/glib/pygoptiongroup.h new file mode 100644 index 0000000..cba6a79 --- /dev/null +++ b/glib/pygoptiongroup.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_OPTIONGROUP_H__ +#define __PYG_OPTIONGROUP_H__ + +extern PyTypeObject PyGOptionGroup_Type; + +typedef struct { + PyObject_HEAD + GOptionGroup *group; + gboolean other_owner, is_in_context; + PyObject *callback; + GSList *strings; /* all strings added with the entries, are freed on + GOptionGroup.destroy() */ +} PyGOptionGroup; + +void pyglib_option_group_register_types(PyObject *d); + +#endif /* __PYG_OPTIONGROUP_H__ */ + + diff --git a/glib/pygsource.c b/glib/pygsource.c new file mode 100644 index 0000000..298b928 --- /dev/null +++ b/glib/pygsource.c @@ -0,0 +1,723 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygtk- Python bindings for the GTK toolkit. + * Copyright (C) 1998-2003 James Henstridge + * Copyright (C) 2005 Oracle + * + * Author: Manish Singh <manish.singh@oracle.com> + * + * pygsource.c: GSource wrapper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <Python.h> +#include <pythread.h> +#include <structmember.h> /* for PyMemberDef */ +#include "pyglib.h" +#include "pyglib-private.h" +#include "pygmaincontext.h" +#include "pygsource.h" + +#define CHECK_DESTROYED(self, ret) G_STMT_START { \ + if ((self)->source == NULL) { \ + PyErr_SetString(PyExc_RuntimeError, "source is destroyed"); \ + return (ret); \ + } \ +} G_STMT_END + + +typedef struct { + PyObject_HEAD + GSource *source; + PyObject *inst_dict; + PyObject *weakreflist; + gboolean python_source; +} PyGSource; + +typedef struct +{ + GSource source; + PyObject *obj; +} PyGRealSource; + +/* glib.Source */ + +PYGLIB_DEFINE_TYPE("glib.Source", PyGSource_Type, PyGSource) + +static PyObject * +source_repr(PyGSource *self, const char *type) +{ + gchar buf[256], *desc; + + if (self->source) { + if (g_source_get_context(self->source)) + desc = "attached"; + else + desc = "unattached"; + } else { + desc = "destroyed"; + } + + if (type) + g_snprintf(buf, sizeof(buf), "<%s glib %s source at 0x%lx>", + desc, type, (long) self); + else + g_snprintf(buf, sizeof(buf), "<%s glib source at 0x%lx>", + desc, (long) self); + + return _PyUnicode_FromString(buf); +} + +static PyObject * +pyg_source_attach(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "context", NULL }; + PyGMainContext *py_context = NULL; + GMainContext *context = NULL; + guint id; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, + "|O!:attach", kwlist, + &PyGMainContext_Type, &py_context)) + return NULL; + + if (py_context) + context = py_context->context; + + CHECK_DESTROYED(self, NULL); + + if (self->python_source) { + PyGRealSource *pysource = (PyGRealSource *)self->source; + Py_INCREF(pysource->obj); + } + + id = g_source_attach(self->source, context); + return _PyLong_FromLong(id); +} + +static PyObject * +pyg_source_destroy(PyGSource *self) +{ + CHECK_DESTROYED(self, NULL); + + if (self->python_source && self->source->context) { + PyGRealSource *pysource = (PyGRealSource *)self->source; + Py_DECREF(pysource->obj); + } + + g_source_destroy(self->source); + self->source = NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_set_callback(PyGSource *self, PyObject *args) +{ + PyObject *first, *callback, *cbargs = NULL, *data; + gint len; + + CHECK_DESTROYED(self, NULL); + + len = PyTuple_Size (args); + if (len < 1) { + PyErr_SetString(PyExc_TypeError, + "set_callback requires at least 1 argument"); + return NULL; + } + + first = PySequence_GetSlice(args, 0, 1); + if (!PyArg_ParseTuple(first, "O:set_callback", &callback)) { + Py_DECREF (first); + return NULL; + } + Py_DECREF(first); + + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "first argument not callable"); + return NULL; + } + + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + + g_source_set_callback(self->source, + _pyglib_handler_marshal, data, + _pyglib_destroy_notify); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_get_context(PyGSource *self) +{ + GMainContext *context; + + CHECK_DESTROYED(self, NULL); + + context = g_source_get_context(self->source); + + if (context) { + return pyglib_main_context_new(context); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject * +pyg_source_add_poll(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", NULL }; + PyGPollFD *fd; + + if (!self->python_source) { + PyErr_SetString(PyExc_TypeError, + "add_poll can only be used with sources " + "implemented in python"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:add_poll", kwlist, + &PyGPollFD_Type, &fd)) + return NULL; + + CHECK_DESTROYED(self, NULL); + + g_source_add_poll(self->source, &fd->pollfd); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_remove_poll(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", NULL }; + PyGPollFD *fd; + + if (!self->python_source) { + PyErr_SetString(PyExc_TypeError, + "remove_poll can only be used with sources " + "implemented in python"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:remove_poll", kwlist, + &PyGPollFD_Type, &fd)) + return NULL; + + CHECK_DESTROYED(self, NULL); + + g_source_remove_poll(self->source, &fd->pollfd); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_get_current_time(PyGSource *self) +{ + GTimeVal timeval; + double ret; + + CHECK_DESTROYED(self, NULL); + + g_source_get_current_time(self->source, &timeval); + ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001; + return PyFloat_FromDouble(ret); +} + +static PyMethodDef pyg_source_methods[] = { + { "attach", (PyCFunction)pyg_source_attach, METH_KEYWORDS }, + { "destroy", (PyCFunction)pyg_source_destroy, METH_NOARGS }, + { "set_callback", (PyCFunction)pyg_source_set_callback, METH_VARARGS }, + { "get_context", (PyCFunction)pyg_source_get_context, METH_NOARGS }, + { "add_poll", (PyCFunction)pyg_source_add_poll, METH_KEYWORDS }, + { "remove_poll", (PyCFunction)pyg_source_remove_poll, METH_KEYWORDS }, + { "get_current_time", (PyCFunction)pyg_source_get_current_time, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +static PyObject * +pyg_source_get_dict(PyGSource *self, void *closure) +{ + if (self->inst_dict == NULL) { + self->inst_dict = PyDict_New(); + if (self->inst_dict == NULL) + return NULL; + } + + Py_INCREF(self->inst_dict); + return self->inst_dict; +} + +static PyObject * +pyg_source_get_priority(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + return _PyLong_FromLong(g_source_get_priority(self->source)); +} + +static int +pyg_source_set_priority(PyGSource *self, PyObject *value, void *closure) +{ + CHECK_DESTROYED(self, -1); + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete priority"); + return -1; + } + + if (!_PyLong_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + g_source_set_priority(self->source, _PyLong_AsLong(value)); + + return 0; +} + +static PyObject * +pyg_source_get_can_recurse(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + return PyBool_FromLong(g_source_get_can_recurse(self->source)); +} + +static int +pyg_source_set_can_recurse(PyGSource *self, PyObject *value, void *closure) +{ + CHECK_DESTROYED(self, -1); + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete can_recurse"); + return -1; + } + + g_source_set_can_recurse(self->source, PyObject_IsTrue(value)); + + return 0; +} + +static PyObject * +pyg_source_get_id(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + if (g_source_get_context(self->source) == NULL) { + PyErr_SetString(PyExc_RuntimeError, "source is not attached"); + return NULL; + } + + return _PyLong_FromLong(g_source_get_id(self->source)); +} + +static PyGetSetDef pyg_source_getsets[] = { + { "__dict__", (getter)pyg_source_get_dict, (setter)0 }, + {"priority", (getter)pyg_source_get_priority, (setter)pyg_source_set_priority }, + {"can_recurse", (getter)pyg_source_get_can_recurse, (setter)pyg_source_set_can_recurse }, + {"id", (getter)pyg_source_get_id, (setter)0 }, + {NULL, 0, 0} +}; + +static PyObject * +pyg_source_repr(PyGSource *self) +{ + return source_repr(self, NULL); +} + +static int +pyg_source_traverse(PyGSource *self, visitproc visit, void *arg) +{ + int ret = 0; + + if (self->inst_dict) ret = visit(self->inst_dict, arg); + if (ret != 0) return ret; + + return 0; +} + +static int +pyg_source_clear(PyGSource *self) +{ + PyObject *tmp; + + tmp = self->inst_dict; + self->inst_dict = NULL; + Py_XDECREF(tmp); + + if (self->source) { + g_source_unref(self->source); + self->source = NULL; + } + + return 0; +} + +static void +pyg_source_dealloc(PyGSource *self) +{ + PyObject_ClearWeakRefs((PyObject *)self); + + PyObject_GC_UnTrack((PyObject *)self); + + pyg_source_clear(self); + + PyObject_GC_Del(self); +} + +static gboolean +pyg_source_prepare(GSource *source, gint *timeout) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *t; + gboolean ret = FALSE; + gboolean got_err = TRUE; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + t = PyObject_CallMethod(pysource->obj, "prepare", NULL); + + if (t == NULL) { + goto bail; + } else if (!PyObject_IsTrue(t)) { + got_err = FALSE; + goto bail; + } else if (!PyTuple_Check(t)) { + PyErr_SetString(PyExc_TypeError, + "source prepare function must return a tuple or False"); + goto bail; + } else if (PyTuple_Size(t) != 2) { + PyErr_SetString(PyExc_TypeError, + "source prepare function return tuple must be exactly " + "2 elements long"); + goto bail; + } + + ret = PyObject_IsTrue(PyTuple_GET_ITEM(t, 0)); + *timeout = _PyLong_AsLong(PyTuple_GET_ITEM(t, 1)); + + if (*timeout == -1 && PyErr_Occurred()) { + ret = FALSE; + goto bail; + } + + got_err = FALSE; + +bail: + if (got_err) + PyErr_Print(); + + Py_XDECREF(t); + + pyglib_gil_state_release(state); + + return ret; +} + +static gboolean +pyg_source_check(GSource *source) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *t; + gboolean ret; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + t = PyObject_CallMethod(pysource->obj, "check", NULL); + + if (t == NULL) { + PyErr_Print(); + ret = FALSE; + } else { + ret = PyObject_IsTrue(t); + Py_DECREF(t); + } + + pyglib_gil_state_release(state); + + return ret; +} + +static gboolean +pyg_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *func, *args, *tuple, *t; + gboolean ret; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + if (callback) { + tuple = user_data; + + func = PyTuple_GetItem(tuple, 0); + args = PyTuple_GetItem(tuple, 1); + } else { + func = Py_None; + args = Py_None; + } + + t = PyObject_CallMethod(pysource->obj, "dispatch", "OO", func, args); + + if (t == NULL) { + PyErr_Print(); + ret = FALSE; + } else { + ret = PyObject_IsTrue(t); + Py_DECREF(t); + } + + pyglib_gil_state_release(state); + + return ret; +} + +static void +pyg_source_finalize(GSource *source) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *func, *t; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + func = PyObject_GetAttrString(pysource->obj, "finalize"); + if (func) { + t = PyObject_CallObject(func, NULL); + Py_DECREF(func); + + if (t == NULL) { + PyErr_Print(); + } else { + Py_DECREF(t); + } + } + + pyglib_gil_state_release(state); +} + +static GSourceFuncs pyg_source_funcs = +{ + pyg_source_prepare, + pyg_source_check, + pyg_source_dispatch, + pyg_source_finalize +}; + +static int +pyg_source_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + PyGRealSource *pysource; + + self->source = g_source_new(&pyg_source_funcs, sizeof(PyGRealSource)); + + pysource = (PyGRealSource *)self->source; + pysource->obj = (PyObject*)self; + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = TRUE; + + return 0; +} + +static void +pyg_source_free(PyObject *op) +{ + PyObject_GC_Del(op); +} + +/* glib.Idle */ + +PYGLIB_DEFINE_TYPE("glib.Idle", PyGIdle_Type, PyGSource) + +static PyObject * +pyg_idle_repr(PyGSource *self) +{ + return source_repr(self, "idle"); +} + +static int +pyg_idle_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "priority", NULL }; + gint priority = G_PRIORITY_DEFAULT_IDLE; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|i:glib.Idle.__init__", kwlist, + &priority)) + return -1; + + self->source = g_idle_source_new (); + + if (priority != G_PRIORITY_DEFAULT_IDLE) + g_source_set_priority(self->source, priority); + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = FALSE; + + return 0; +} + +/* glib.Timeout */ + +PYGLIB_DEFINE_TYPE("glib.Timeout", PyGTimeout_Type, PyGSource) + +static PyObject * +pyg_timeout_repr(PyGSource *self) +{ + return source_repr(self, "timeout"); +} + +static int +pyg_timeout_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "interval", "priority", NULL }; + gint priority = G_PRIORITY_DEFAULT; + guint interval; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "I|i:glib.Timeout.__init__", kwlist, + &interval, &priority)) + return -1; + + self->source = g_timeout_source_new(interval); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority(self->source, priority); + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = FALSE; + + return 0; +} + +/* glib.PollFD */ + +PYGLIB_DEFINE_TYPE("glib.PollFD", PyGPollFD_Type, PyGPollFD) + +static PyMemberDef pyg_poll_fd_members[] = { + { "fd", T_INT, offsetof(PyGPollFD, pollfd.fd), READONLY }, + { "events", T_USHORT, offsetof(PyGPollFD, pollfd.events), READONLY }, + { "revents", T_USHORT, offsetof(PyGPollFD, pollfd.revents), READONLY }, + { NULL, 0, 0, 0 } +}; + +static void +pyg_poll_fd_dealloc(PyGPollFD *self) +{ + Py_XDECREF(self->fd_obj); + PyObject_DEL(self); +} + +static PyObject * +pyg_poll_fd_repr(PyGPollFD *self) +{ + return _PyUnicode_FromFormat("<GPollFD %d (%d) at 0x%lx>", + self->pollfd.fd, self->pollfd.events, + (long)self); +} + +static int +pyg_poll_fd_init(PyGPollFD *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", "events", NULL }; + PyObject *o; + gint fd; + gushort events; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "OH:glib.PollFD.__init__", kwlist, + &o, &events)) + return -1; + + fd = PyObject_AsFileDescriptor(o); + if (fd == -1) + return -1; + + self->pollfd.fd = fd; + self->pollfd.events = events; + self->pollfd.revents = 0; + + Py_INCREF(o); + self->fd_obj = o; + + return 0; +} + +void +pyglib_source_register_types(PyObject *d) +{ + PyGSource_Type.tp_flags = (Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC); + PyGSource_Type.tp_init = (initproc)pyg_source_init; + PyGSource_Type.tp_free = (freefunc)pyg_source_free; + PyGSource_Type.tp_dealloc = (destructor)pyg_source_dealloc; + PyGSource_Type.tp_methods = pyg_source_methods; + PyGSource_Type.tp_repr = (reprfunc)pyg_source_repr; + PyGSource_Type.tp_traverse = (traverseproc)pyg_source_traverse; + PyGSource_Type.tp_clear = (inquiry)pyg_source_clear; + PyGSource_Type.tp_getset = pyg_source_getsets; + PyGSource_Type.tp_weaklistoffset = offsetof(PyGSource, weakreflist); + PyGSource_Type.tp_dictoffset = offsetof(PyGSource, inst_dict); + PYGLIB_REGISTER_TYPE(d, PyGSource_Type, "Source"); + + PyGIdle_Type.tp_repr = (reprfunc)pyg_idle_repr; + PyGIdle_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + PyGIdle_Type.tp_base = (PyTypeObject *)&PyGSource_Type; + PyGIdle_Type.tp_init = (initproc)pyg_idle_init; + PYGLIB_REGISTER_TYPE(d, PyGIdle_Type, "Idle"); + + PyGTimeout_Type.tp_repr = (reprfunc)pyg_timeout_repr; + PyGTimeout_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + PyGTimeout_Type.tp_base = (PyTypeObject *)&PyGSource_Type; + PyGTimeout_Type.tp_init = (initproc)pyg_timeout_init; + PYGLIB_REGISTER_TYPE(d, PyGTimeout_Type, "Timeout"); + + PyGPollFD_Type.tp_dealloc = (destructor)pyg_poll_fd_dealloc; + PyGPollFD_Type.tp_repr = (reprfunc)pyg_poll_fd_repr; + PyGPollFD_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyGPollFD_Type.tp_members = pyg_poll_fd_members; + PyGPollFD_Type.tp_init = (initproc)pyg_poll_fd_init; + PYGLIB_REGISTER_TYPE(d, PyGPollFD_Type, "PollFD"); +} diff --git a/glib/pygsource.h b/glib/pygsource.h new file mode 100644 index 0000000..bf2c673 --- /dev/null +++ b/glib/pygsource.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_SOURCE_H__ +#define __PYG_SOURCE_H__ + +extern PyTypeObject PyGSource_Type; +extern PyTypeObject PyGIdle_Type; +extern PyTypeObject PyGTimeout_Type; +extern PyTypeObject PyGPollFD_Type; + +typedef struct +{ + PyObject_HEAD + GPollFD pollfd; + PyObject *fd_obj; +} PyGPollFD; + +void pyglib_source_register_types(PyObject *d); + +#endif /* __PYG_SOURCE_H__ */ diff --git a/glib/pygspawn.c b/glib/pygspawn.c new file mode 100644 index 0000000..cded501 --- /dev/null +++ b/glib/pygspawn.c @@ -0,0 +1,263 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * pygspawn.c: wrapper for the glib library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include <Python.h> +#include <glib.h> + +#include "pyglib.h" +#include "pyglib-private.h" + +struct _PyGChildSetupData { + PyObject *func; + PyObject *data; +}; + +PYGLIB_DEFINE_TYPE("glib.Pid", PyGPid_Type, _PyLongObject) + +static PyObject * +pyg_pid_close(PyObject *self, PyObject *args, PyObject *kwargs) +{ + g_spawn_close_pid(_PyLong_AsLong(self)); + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef pyg_pid_methods[] = { + { "close", (PyCFunction)pyg_pid_close, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +static void +pyg_pid_free(PyObject *gpid) +{ + g_spawn_close_pid((GPid) _PyLong_AsLong(gpid)); + _PyLong_Type.tp_free((void *) gpid); +} + +static int +pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyErr_SetString(PyExc_TypeError, "glib.Pid cannot be manually instantiated"); + return -1; +} + +PyObject * +pyg_pid_new(GPid pid) +{ + _PyLongObject *pygpid; + pygpid = PyObject_NEW(_PyLongObject, &PyGPid_Type); + +#if PY_VERSION_HEX >= 0x03000000 +# warning "FIXME: figure out how to subclass long" +#else + pygpid->ob_ival = pid; +#endif + return (PyObject *) pygpid; +} + +static void +_pyg_spawn_async_callback(gpointer user_data) +{ + struct _PyGChildSetupData *data; + PyObject *retval; + PyGILState_STATE gil; + + data = (struct _PyGChildSetupData *) user_data; + gil = pyglib_gil_state_ensure(); + if (data->data) + retval = PyObject_CallFunction(data->func, "O", data->data); + else + retval = PyObject_CallFunction(data->func, NULL); + if (retval) + Py_DECREF(retval); + else + PyErr_Print(); + Py_DECREF(data->func); + Py_XDECREF(data->data); + g_slice_free(struct _PyGChildSetupData, data); + pyglib_gil_state_release(gil); +} + +PyObject * +pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "argv", "envp", "working_directory", "flags", + "child_setup", "user_data", "standard_input", + "standard_output", "standard_error", NULL }; + PyObject *pyargv, *pyenvp = NULL; + char **argv, **envp = NULL; + PyObject *func = Py_None, *user_data = NULL; + char *working_directory = NULL; + int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1; + PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL; + gint *standard_input, *standard_output, *standard_error; + struct _PyGChildSetupData *callback_data = NULL; + GError *error = NULL; + GPid child_pid = -1; + Py_ssize_t len, i; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:glib.spawn_async", + kwlist, + &pyargv, &pyenvp, &working_directory, &flags, + &func, &user_data, + &pystdin, &pystdout, &pystderr)) + return NULL; + + if (pystdin && PyObject_IsTrue(pystdin)) + standard_input = &_stdin; + else + standard_input = NULL; + + if (pystdout && PyObject_IsTrue(pystdout)) + standard_output = &_stdout; + else + standard_output = NULL; + + if (pystderr && PyObject_IsTrue(pystderr)) + standard_error = &_stderr; + else + standard_error = NULL; + + /* parse argv */ + if (!PySequence_Check(pyargv)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "first argument must be a sequence of strings"); + return NULL; + } + len = PySequence_Length(pyargv); + argv = g_new0(char *, len + 1); + for (i = 0; i < len; ++i) { + PyObject *tmp = PySequence_ITEM(pyargv, i); + if (!_PyUnicode_Check(tmp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "first argument must be a sequence of strings"); + g_free(argv); + Py_XDECREF(tmp); + return NULL; + } + argv[i] = _PyUnicode_AsString(tmp); + Py_DECREF(tmp); + } + + /* parse envp */ + if (pyenvp) { + if (!PySequence_Check(pyenvp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "second argument must be a sequence of strings"); + g_free(argv); + return NULL; + } + len = PySequence_Length(pyenvp); + envp = g_new0(char *, len + 1); + for (i = 0; i < len; ++i) { + PyObject *tmp = PySequence_ITEM(pyenvp, i); + if (!_PyUnicode_Check(tmp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "second argument must be a sequence of strings"); + g_free(envp); + Py_XDECREF(tmp); + g_free(argv); + return NULL; + } + envp[i] = _PyUnicode_AsString(tmp); + Py_DECREF(tmp); + } + } + + if (func != Py_None) { + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "child_setup parameter must be callable or None"); + g_free(argv); + if (envp) + g_free(envp); + return NULL; + } + callback_data = g_slice_new(struct _PyGChildSetupData); + callback_data->func = func; + callback_data->data = user_data; + Py_INCREF(callback_data->func); + if (callback_data->data) + Py_INCREF(callback_data->data); + } + + if (!g_spawn_async_with_pipes(working_directory, argv, envp, flags, + (func != Py_None ? _pyg_spawn_async_callback : NULL), + callback_data, &child_pid, + standard_input, + standard_output, + standard_error, + &error)) + + + { + g_free(argv); + if (envp) g_free(envp); + if (callback_data) { + Py_DECREF(callback_data->func); + Py_XDECREF(callback_data->data); + g_slice_free(struct _PyGChildSetupData, callback_data); + } + pyglib_error_check(&error); + return NULL; + } + g_free(argv); + if (envp) g_free(envp); + + if (standard_input) + pystdin = _PyLong_FromLong(*standard_input); + else { + Py_INCREF(Py_None); + pystdin = Py_None; + } + + if (standard_output) + pystdout = _PyLong_FromLong(*standard_output); + else { + Py_INCREF(Py_None); + pystdout = Py_None; + } + + if (standard_error) + pystderr = _PyLong_FromLong(*standard_error); + else { + Py_INCREF(Py_None); + pystderr = Py_None; + } + + return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr); +} + +void +pyglib_spawn_register_types(PyObject *d) +{ + PyGPid_Type.tp_base = &_PyLong_Type; + PyGPid_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyGPid_Type.tp_methods = pyg_pid_methods; + PyGPid_Type.tp_init = pyg_pid_tp_init; + PyGPid_Type.tp_free = (freefunc)pyg_pid_free; + PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid"); +} diff --git a/glib/pygspawn.h b/glib/pygspawn.h new file mode 100644 index 0000000..2e8dd3c --- /dev/null +++ b/glib/pygspawn.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYG_PID_H__ +#define __PYG_PID_H__ + +PyObject * pyg_pid_new(GPid pid); +void pyglib_spawn_register_types(PyObject *d); + +PyObject * pyglib_spawn_async(PyObject *self, PyObject *args, PyObject *kwargs); + + +#endif /* __PYG_PID_H__ */ + |