Skip to content

Instantly share code, notes, and snippets.

@jaylett
Created August 6, 2016 18:59
Show Gist options
  • Save jaylett/7919a19d78eea3e933cab19e296b73fd to your computer and use it in GitHub Desktop.
Save jaylett/7919a19d78eea3e933cab19e296b73fd to your computer and use it in GitHub Desktop.
python3 bindings
This is pretty unpleasant, and feels very fragile, but I can't figure out another
way of doing it without changes to SWIG or dropping the xapian/ package layout.
It may well be that having xapian.py and _xapian.so (and similar) is actually
the better way of doing it; it's certainly a lot cleaner.
Note that this using these changes means that the docs are built properly,
including the full module documentation via the docstrings. (This throws up
a large number of warnings, but that's a secondary issue.)
diff --git a/xapian-bindings/python3/Makefile.am b/xapian-bindings/python3/Makef
ile.am
index 2301658..edc7031 100644
--- a/xapian-bindings/python3/Makefile.am
+++ b/xapian-bindings/python3/Makefile.am
@@ -45,8 +45,11 @@ pkgpylibdir = @PYTHON3_LIB@/xapian
# Install as _DATA rather than _SCRIPTS because we don't want to make these
# executable (they don't have a #! line).
pkgpylib_DATA = xapian/__init__.py \
+ xapian/loader.py \
xapian/__pycache__/__init__.@PYTHON3_CACHE_TAG@.pyc \
- xapian/__pycache__/__init__.@PYTHON3_CACHE_OPT1_EXT@
+ xapian/__pycache__/__init__.@PYTHON3_CACHE_OPT1_EXT@ \
+ xapian/__pycache__/loader.@PYTHON3_CACHE_TAG@.pyc \
+ xapian/__pycache__/loader.@PYTHON3_CACHE_OPT1_EXT@
pkgpylib_LTLIBRARIES = _xapian.la
@@ -68,18 +71,31 @@ _xapian_la_SOURCES = xapian_wrap.cc
_xapian_la_LIBADD = $(XAPIAN_LIBS) $(PYTHON3_LIBS)
# We want `xapian/__init__.py` rather than xapian.py so the module is treated
-# as a package.
-xapian/__init__.py: xapian.py
+# as a package. However SWIG 3 doesn't support this, so we have to have an
+# indirect loader.
+xapian/__init__.py: xapian_init.py xapian/loader.py
$(MKDIR_P) xapian
- cp `test -f xapian.py || echo '$(srcdir)/'`xapian.py xapian/__init__.py
+ cp `test -f xapian_init.py || echo '$(srcdir)/'`xapian_init.py xapian/__init__.py
+
+xapian/loader.py: xapian.py
+ $(MKDIR_P) xapian
+ cp `test -f xapian.py || echo '$(srcdir)/'`xapian.py xapian/loader.py
+
+# The two loader compiled objects we generate implicitly by importing
+# the entire library.
+xapian/__pycache__/loader.@PYTHON3_CACHE_TAG@.pyc: xapian/__init__.py xapian/loader.py xapian/_xapian$(PYTHON3_SO)
+
+xapian/__pycache__/loader.@PYTHON3_CACHE_OPT1_EXT@: xapian/__init__.py xapian/loader.py xapian/_xapian$(PYTHON3_SO)
# We "import _xapian" first so that if we fail to import the glue library
# we don't generate a broken .pyc or .pyo.
xapian/__pycache__/__init__.@PYTHON3_CACHE_TAG@.pyc: xapian/__init__.py xapian/_xapian$(PYTHON3_SO)
- PYTHONPATH="xapian:$$PYTHONPATH" $(PYTHON3) -c 'import _xapian; import xapian'
+ PYTHONPATH="xapian:$$PYTHONPATH" $(PYTHON3) -c 'import _xapian'
+ $(PYTHON3) -c 'import xapian'
xapian/__pycache__/__init__.@PYTHON3_CACHE_OPT1_EXT@: xapian/__init__.py xapian/_xapian$(PYTHON3_SO)
- PYTHONPATH="xapian:$$PYTHONPATH" $(PYTHON3) -O -c 'import _xapian; import xapian'
+ PYTHONPATH="xapian:$$PYTHONPATH" $(PYTHON3) -O -c 'import _xapian'
+ $(PYTHON3) -O -c 'import xapian'
xapian/_xapian$(PYTHON3_SO): _xapian.la
$(MKDIR_P) xapian
@@ -91,8 +107,11 @@ xapian/_xapian$(PYTHON3_SO): _xapian.la
CLEANFILES = \
xapian/_xapian$(PYTHON3_SO) \
xapian/__init__.py \
+ xapian/loader.py \
xapian/__pycache__/__init__.@PYTHON3_CACHE_TAG@.pyc \
xapian/__pycache__/__init__.@PYTHON3_CACHE_OPT1_EXT@\+ xapian/__pycache__/loader.@PYTHON3_CACHE_TAG@.pyc \
+ xapian/__pycache__/loader.@PYTHON3_CACHE_OPT1_EXT@\
$(srcdir)/*.pyc
# Clean the xapian directory which we created, if it's empty, and any
# SWIG 3 cannot import the wrapper relative to a shadow wrapper which
# is a package's __init__, so we install the shadow wrapper as
# xapian.loader and then bring things in from there.
from xapian import loader
# Get the docstring in first.
__doc__ = loader.__doc__
# Then bring in all the members.
import inspect
for n, v in inspect.getmembers(loader):
if n not in ('__name__', '__path__', '__package__'):
if hasattr(v, '__module__') and v.__module__ == 'xapian.loader':
v.__module__ = 'xapian'
globals()[n] = v
# Tidy up our namespace.
del n, v, inspect, loader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment