]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Create the psycopg3-binary package
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 22 Nov 2020 21:51:20 +0000 (21:51 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 22 Nov 2020 23:15:05 +0000 (23:15 +0000)
README.rst
psycopg3/psycopg3/pq/__init__.py
psycopg3/setup.py
tests/fix_pq.py
tools/build_wheels.sh

index 82f21bcfe7b43e653de49682f2e4cfc5d8d8c5e0..dd1635ae4b4f6fd404d6acd07201b11973828496 100644 (file)
@@ -49,5 +49,5 @@ and to run the tests::
     tox -c psycopg3_c -s
 
 Please look at the commands definitions in the ``tox.ini`` files if you want
-to run some of them interacively: the dependency should be already in your
+to run some of them interactively: the dependency should be already in your
 virtualenv.
index fa21c491b656a730c32085aa5d18e8669281b893..8ebee38d58a568f3031634fab58bad56ad41ca53 100644 (file)
@@ -39,15 +39,33 @@ Escaping: Type[proto.Escaping]
 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)
@@ -55,18 +73,11 @@ def import_from_libpq() -> None:
                 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)
@@ -74,16 +85,15 @@ def import_from_libpq() -> None:
                 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")
index 858438b006367cfd5f380bb84a5956e6b5077673..b0fe3b0bcd1dba5178404c4ac793d50365153122 100644 (file)
@@ -23,7 +23,14 @@ with open("psycopg3/version.py") as f:
     version = m.group(1)
 
 extras_require = {
-    "c": [f"psycopg3-c == {version}"],
+    # Install the C extension module (requires dev tools)
+    "c": [
+        f"psycopg3-c == {version}",
+    ],
+    # Install the stand-alone C extension module
+    "binary": [
+        f"psycopg3-binary == {version}",
+    ],
     "test": [
         "pytest >= 6, < 6.1",
         "pytest-asyncio >= 0.14.0, < 0.15",
index 24d8d8e441f4f71f1db642ed35e836073fc73872..551032bffcdf67de9a9cf06396d9965eef5b3f80 100644 (file)
@@ -36,8 +36,18 @@ def libpq():
     """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):
index 548ac8c2ac866c6bfacdf11ac8be13464b7e8b67..9ce9481890b9badc21fe9ce2d4058d06938f645e 100755 (executable)
@@ -41,10 +41,19 @@ export PATH="/usr/pgsql-13/bin/:$PATH"
 # 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
@@ -63,6 +72,6 @@ rm -v /usr/pgsql-13/lib/libpq.*
 # 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