# 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")
# 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
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`.
import os
import sys
+import ctypes
from typing import Iterator, List, NamedTuple
from tempfile import TemporaryFile
@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: