]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
refactor: add find_libpq_full_path() to use both in library and tests
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 5 Sep 2022 11:09:33 +0000 (12:09 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 5 Sep 2022 11:35:05 +0000 (12:35 +0100)
psycopg/psycopg/pq/_pq_ctypes.py
psycopg/psycopg/pq/misc.py
tests/fix_pq.py

index 58b9bd4b95aac0a840f4ee5f9ae08094932cfa86..4f9d00fb2281d88bfc2ea2baaec5ba03c8523fde 100644 (file)
@@ -4,43 +4,17 @@ libpq access using ctypes
 
 # Copyright (C) 2020 The Psycopg Team
 
-import os
+import sys
 import ctypes
 import ctypes.util
-import sys
 from ctypes import Structure, CFUNCTYPE, POINTER
 from ctypes import c_char, c_char_p, c_int, c_size_t, c_ubyte, c_uint, c_void_p
 from typing import List, Optional, Tuple
 
+from .misc import find_libpq_full_path
 from ..errors import NotSupportedError
 
-import logging
-
-logger = logging.getLogger("psycopg")
-
-
-if sys.platform == "win32":
-    libname = ctypes.util.find_library("libpq.dll")
-
-elif sys.platform == "darwin":
-    libname = ctypes.util.find_library("libpq.dylib")
-    # (hopefully) temporary hack: libpq not in a standard place
-    # https://github.com/orgs/Homebrew/discussions/3595
-    # If pg_config is available and agrees, let's use its indications.
-    if not libname:
-        try:
-            import subprocess as sp
-
-            libdir = sp.check_output(["pg_config", "--libdir"]).strip().decode()
-            libname = os.path.join(libdir, "libpq.dylib")
-            if not os.path.exists(libname):
-                libname = None
-        except Exception as ex:
-            logger.debug("couldn't use pg_config to find libpq: %s", ex)
-
-else:
-    libname = ctypes.util.find_library("pq")
-
+libname = find_libpq_full_path()
 if not libname:
     raise ImportError("libpq library not found")
 
index 9ad16bec46d990e51d99037a344e36ad7bd62bb2..92be04965407bad8bf4907b0a20fa69ae149911d 100644 (file)
@@ -4,12 +4,19 @@ Various functionalities to make easier to work with the libpq.
 
 # Copyright (C) 2020 The Psycopg Team
 
+import os
+import sys
+import logging
+import ctypes.util
 from typing import cast, NamedTuple, Optional, Union
+from functools import lru_cache
 
 from .abc import PGconn, PGresult
 from ._enums import ConnStatus, TransactionStatus, PipelineStatus
 from .._encodings import pgconn_encoding
 
+logger = logging.getLogger("psycopg.pq")
+
 OK = ConnStatus.OK
 
 
@@ -39,6 +46,33 @@ class PGresAttDesc(NamedTuple):
     atttypmod: int
 
 
+@lru_cache()
+def find_libpq_full_path() -> Optional[str]:
+    if sys.platform == "win32":
+        libname = ctypes.util.find_library("libpq.dll")
+
+    elif sys.platform == "darwin":
+        libname = ctypes.util.find_library("libpq.dylib")
+        # (hopefully) temporary hack: libpq not in a standard place
+        # https://github.com/orgs/Homebrew/discussions/3595
+        # If pg_config is available and agrees, let's use its indications.
+        if not libname:
+            try:
+                import subprocess as sp
+
+                libdir = sp.check_output(["pg_config", "--libdir"]).strip().decode()
+                libname = os.path.join(libdir, "libpq.dylib")
+                if not os.path.exists(libname):
+                    libname = None
+            except Exception as ex:
+                logger.debug("couldn't use pg_config to find libpq: %s", ex)
+
+    else:
+        libname = ctypes.util.find_library("pq")
+
+    return libname
+
+
 def error_message(obj: Union[PGconn, PGresult], encoding: str = "utf8") -> str:
     """
     Return an error message from a `PGconn` or `PGresult`.
index a17d2854f4f47e1ffb2f3a326f29b5bea3dfd446..6811a26c32a3337bf0d1364684be9c06c82ee3a9 100644 (file)
@@ -1,5 +1,6 @@
 import os
 import sys
+import ctypes
 from typing import Iterator, List, NamedTuple
 from tempfile import TemporaryFile
 
@@ -46,14 +47,11 @@ def pytest_runtest_setup(item):
 @pytest.fixture
 def libpq():
     """Return a ctypes wrapper to access the libpq."""
-    import ctypes.util
-
     try:
+        from psycopg.pq.misc import find_libpq_full_path
+
         # Not available when testing the binary package
-        if sys.platform == "win32":
-            libname = ctypes.util.find_library("libpq.dll")
-        else:
-            libname = ctypes.util.find_library("pq")
+        libname = find_libpq_full_path()
         assert libname, "libpq libname not found"
         return ctypes.pydll.LoadLibrary(libname)
     except Exception as e: