From: Daniele Varrazzo Date: Mon, 5 Sep 2022 11:09:33 +0000 (+0100) Subject: refactor: add find_libpq_full_path() to use both in library and tests X-Git-Tag: 3.1.1~1^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=886e3198b01a5630f2279c6385fc685fa9a5143a;p=thirdparty%2Fpsycopg.git refactor: add find_libpq_full_path() to use both in library and tests --- diff --git a/psycopg/psycopg/pq/_pq_ctypes.py b/psycopg/psycopg/pq/_pq_ctypes.py index 58b9bd4b9..4f9d00fb2 100644 --- a/psycopg/psycopg/pq/_pq_ctypes.py +++ b/psycopg/psycopg/pq/_pq_ctypes.py @@ -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") diff --git a/psycopg/psycopg/pq/misc.py b/psycopg/psycopg/pq/misc.py index 9ad16bec4..92be04965 100644 --- a/psycopg/psycopg/pq/misc.py +++ b/psycopg/psycopg/pq/misc.py @@ -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`. diff --git a/tests/fix_pq.py b/tests/fix_pq.py index a17d2854f..6811a26c3 100644 --- a/tests/fix_pq.py +++ b/tests/fix_pq.py @@ -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: