def import_from_libpq() -> None:
"""
Import pq objects implementation from the best libpw wrapper available.
+
+ If an implementation is requested try to import only it, otherwise
+ try to import the best implementation available.
"""
+ # import these names into the module on success as side effect
global __impl__, version, PGconn, PGresult, Conninfo, Escaping
impl = os.environ.get("PSYCOPG3_IMPL", "").lower()
+ module = None
+ # The best implementation: fast but requires the system libpq installed
if not impl or impl == "c":
try:
# TODO: extension module not recognised by mypy?
- from psycopg3_c import pq_cython # type: ignore
+ from psycopg3_c import pq_cython as module # type: ignore
+ except Exception as e:
+ if not impl:
+ logger.debug("C pq wrapper not available: %s", e)
+ else:
+ raise ImportError(
+ f"requested pq implementation '{impl}' not available"
+ ) from e
+
+ # Second best implementation: fast and stand-alone
+ if not module and (not impl or impl == "binary"):
+ try:
+ from psycopg3_binary import pq_cython as module # type: ignore
except Exception as e:
if not impl:
logger.debug("C pq wrapper not available: %s", e)
raise ImportError(
f"requested pq implementation '{impl}' not available"
) from e
- else:
- __impl__ = pq_cython.__impl__
- version = pq_cython.version
- PGconn = pq_cython.PGconn
- PGresult = pq_cython.PGresult
- Conninfo = pq_cython.Conninfo
- Escaping = pq_cython.Escaping
- return
-
- if not impl or impl == "python":
+
+ # Pure Python implementation, slow and requires the system libpq installed.
+ if not module and (not impl or impl == "python"):
try:
- from . import pq_ctypes
+ from . import pq_ctypes as module # type: ignore[no-redef]
except Exception as e:
if not impl:
logger.debug("python pq wrapper not available: %s", e)
raise ImportError(
f"requested pq implementation '{impl}' not available"
) from e
- else:
- __impl__ = pq_ctypes.__impl__
- version = pq_ctypes.version
- PGconn = pq_ctypes.PGconn
- PGresult = pq_ctypes.PGresult
- Conninfo = pq_ctypes.Conninfo
- Escaping = pq_ctypes.Escaping
- return
-
- if impl:
+
+ if module:
+ __impl__ = module.__impl__
+ version = module.version
+ PGconn = module.PGconn
+ PGresult = module.PGresult
+ Conninfo = module.Conninfo
+ Escaping = module.Escaping
+ elif impl:
raise ImportError(f"requested pq impementation '{impl}' unknown")
else:
raise ImportError("no pq wrapper available")
"""Return a ctypes wrapper to access the libpq."""
import ctypes.util
- libname = ctypes.util.find_library("pq")
- return ctypes.pydll.LoadLibrary(libname)
+ try:
+ # Not available when testing the binary package
+ libname = ctypes.util.find_library("pq")
+ assert libname, "libpq libname not found"
+ return ctypes.pydll.LoadLibrary(libname)
+ except Exception as e:
+ from psycopg3 import pq
+
+ if pq.__impl__ == "binary":
+ pytest.skip(f"can't load libpq for testing: {e}")
+ else:
+ raise
def check_libpq_version(got, want):
# Using --global-option="-L/usr/pgsql-13/lib/" disables wheels, so no-go.
cp -avr /usr/pgsql-13/lib/* /usr/lib/
+# Patch a copy of the c package to name it -binary
+cp -r /psycopg3/psycopg3_c /psycopg3_binary
+mv /psycopg3_binary/{psycopg3_c,psycopg3_binary}/
+sed -i 's/psycopg3-c/psycopg3-binary/' /psycopg3_binary/setup.cfg
+sed -i "s/__impl__[[:space:]]*=.*/__impl__ = 'binary'/" \
+ /psycopg3_binary/psycopg3_binary/pq_cython.pyx
+find /psycopg3_binary/ -name \*.pyx -or -name \*.pxd -or -name \*.py \
+ | xargs sed -i 's/\bpsycopg3_c\b/psycopg3_binary/'
+
# Compile wheels
for PYBIN in /opt/python/*/bin; do
if [[ $PYBIN =~ "cp35" ]]; then continue; fi
- "${PYBIN}/pip" wheel /psycopg3/psycopg3_c/ --no-deps -w /tmpwheels/
+ "${PYBIN}/pip" wheel /psycopg3_binary/ --no-deps -w /tmpwheels/
done
# Bundle external shared libraries into the wheels
# Install packages and test
for PYBIN in /opt/python/*/bin/; do
if [[ $PYBIN =~ "cp35" ]]; then continue; fi
- "${PYBIN}/pip" install psycopg3[c,test]==$version -f /psycopg3/wheels
- PSYCOPG3_IMPL=c "${PYBIN}/pytest" /psycopg3/tests -m "not slow"
+ "${PYBIN}/pip" install psycopg3[binary,test]==$version -f /psycopg3/wheels
+ PSYCOPG3_IMPL=binary "${PYBIN}/pytest" /psycopg3/tests -m "not slow"
done