Skip to content

Commit a7f2802

Browse files
committed
refactor: less verbose pattern to manage optional libpq functions
1 parent 066d4ed commit a7f2802

File tree

1 file changed

+67
-180
lines changed

1 file changed

+67
-180
lines changed

psycopg/psycopg/pq/_pq_ctypes.py

Lines changed: 67 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import ctypes.util
1010
from ctypes import Structure, CFUNCTYPE, POINTER
1111
from ctypes import c_char, c_char_p, c_int, c_size_t, c_ubyte, c_uint, c_void_p
12-
from typing import Any, List, Optional, Tuple
12+
from typing import Any, List, NoReturn, Tuple
1313

1414
from .misc import find_libpq_full_path
1515
from ..errors import NotSupportedError
@@ -185,24 +185,23 @@ class PGresAttDesc_struct(Structure):
185185
PQhost.argtypes = [PGconn_ptr]
186186
PQhost.restype = c_char_p
187187

188-
_PQhostaddr = None
189188

190-
if libpq_version >= 120000:
191-
_PQhostaddr = pq.PQhostaddr
192-
_PQhostaddr.argtypes = [PGconn_ptr]
193-
_PQhostaddr.restype = c_char_p
194-
195-
196-
def PQhostaddr(pgconn: PGconn_struct) -> bytes:
197-
if not _PQhostaddr:
189+
def not_supported_before(fname: str, pgversion: int) -> Any:
190+
def not_supported(*args: Any, **kwargs: Any) -> NoReturn:
198191
raise NotSupportedError(
199-
"PQhostaddr requires libpq from PostgreSQL 12,"
200-
f" {libpq_version} available instead"
192+
f"{fname} requires libpq from PostgreSQL {pgversion} on the client;"
193+
f" version {libpq_version // 10000} available instead"
201194
)
202195

203-
rv: bytes = _PQhostaddr(pgconn)
204-
return rv
196+
return not_supported
197+
205198

199+
if libpq_version >= 120000:
200+
PQhostaddr = pq.PQhostaddr
201+
PQhostaddr.argtypes = [PGconn_ptr]
202+
PQhostaddr.restype = c_char_p
203+
else:
204+
PQhostaddr = not_supported_before("PQhostaddr", 12)
206205

207206
PQport = pq.PQport
208207
PQport.argtypes = [PGconn_ptr]
@@ -306,38 +305,18 @@ def PQhostaddr(pgconn: PGconn_struct) -> bytes:
306305
PQdescribePortal.argtypes = [PGconn_ptr, c_char_p]
307306
PQdescribePortal.restype = PGresult_ptr
308307

309-
_PQclosePrepared = None
310-
_PQclosePortal = None
311-
312308
if libpq_version >= 170000:
313-
_PQclosePrepared = pq.PQclosePrepared
314-
_PQclosePrepared.argtypes = [PGconn_ptr, c_char_p]
315-
_PQclosePrepared.restype = PGresult_ptr
316-
317-
_PQclosePortal = pq.PQclosePortal
318-
_PQclosePortal.argtypes = [PGconn_ptr, c_char_p]
319-
_PQclosePortal.restype = PGresult_ptr
320-
309+
PQclosePrepared = pq.PQclosePrepared
310+
PQclosePrepared.argtypes = [PGconn_ptr, c_char_p]
311+
PQclosePrepared.restype = PGresult_ptr
321312

322-
def PQclosePrepared(pgconn: PGconn_struct, name: str) -> int:
323-
if not _PQclosePrepared:
324-
raise NotSupportedError(
325-
"PQclosePrepared requires libpq from PostgreSQL 17,"
326-
f" {libpq_version} available instead"
327-
)
328-
rv: int = _PQclosePrepared(pgconn, name)
329-
return rv
330-
331-
332-
def PQclosePortal(pgconn: PGconn_struct, name: str) -> int:
333-
if not _PQclosePortal:
334-
raise NotSupportedError(
335-
"PQclosePortal requires libpq from PostgreSQL 17,"
336-
f" {libpq_version} available instead"
337-
)
338-
rv: int = _PQclosePortal(pgconn, name)
339-
return rv
313+
PQclosePortal = pq.PQclosePortal
314+
PQclosePortal.argtypes = [PGconn_ptr, c_char_p]
315+
PQclosePortal.restype = PGresult_ptr
340316

317+
else:
318+
PQclosePrepared = not_supported_before("PQclosePrepared", 17)
319+
PQclosePortal = not_supported_before("PQclosePrepared", 17)
341320

342321
PQresultStatus = pq.PQresultStatus
343322
PQresultStatus.argtypes = [PGresult_ptr]
@@ -532,38 +511,18 @@ def PQclosePortal(pgconn: PGconn_struct, name: str) -> int:
532511
PQsendDescribePortal.argtypes = [PGconn_ptr, c_char_p]
533512
PQsendDescribePortal.restype = c_int
534513

535-
_PQsendClosePrepared = None
536-
_PQsendClosePortal = None
537-
538514
if libpq_version >= 170000:
539-
_PQsendClosePrepared = pq.PQsendClosePrepared
540-
_PQsendClosePrepared.argtypes = [PGconn_ptr, c_char_p]
541-
_PQsendClosePrepared.restype = c_int
515+
PQsendClosePrepared = pq.PQsendClosePrepared
516+
PQsendClosePrepared.argtypes = [PGconn_ptr, c_char_p]
517+
PQsendClosePrepared.restype = c_int
542518

543-
_PQsendClosePortal = pq.PQsendClosePortal
544-
_PQsendClosePortal.argtypes = [PGconn_ptr, c_char_p]
545-
_PQsendClosePortal.restype = c_int
546-
547-
548-
def PQsendClosePrepared(pgconn: PGconn_struct, name: str) -> int:
549-
if not _PQsendClosePrepared:
550-
raise NotSupportedError(
551-
"PQsendClosePrepared requires libpq from PostgreSQL 17,"
552-
f" {libpq_version} available instead"
553-
)
554-
rv: int = _PQsendClosePrepared(pgconn, name)
555-
return rv
556-
557-
558-
def PQsendClosePortal(pgconn: PGconn_struct, name: str) -> int:
559-
if not _PQsendClosePortal:
560-
raise NotSupportedError(
561-
"PQsendClosePortal requires libpq from PostgreSQL 17,"
562-
f" {libpq_version} available instead"
563-
)
564-
rv: int = _PQsendClosePortal(pgconn, name)
565-
return rv
519+
PQsendClosePortal = pq.PQsendClosePortal
520+
PQsendClosePortal.argtypes = [PGconn_ptr, c_char_p]
521+
PQsendClosePortal.restype = c_int
566522

523+
else:
524+
PQsendClosePrepared = not_supported_before("PQsendClosePrepared", 17)
525+
PQsendClosePortal = not_supported_before("PQsendClosePortal", 17)
567526

568527
PQgetResult = pq.PQgetResult
569528
PQgetResult.argtypes = [PGconn_ptr]
@@ -640,23 +599,12 @@ def PQsendClosePortal(pgconn: PGconn_struct, name: str) -> int:
640599
PQtrace.argtypes = [PGconn_ptr, FILE_ptr]
641600
PQtrace.restype = None
642601

643-
_PQsetTraceFlags = None
644-
645602
if libpq_version >= 140000:
646-
_PQsetTraceFlags = pq.PQsetTraceFlags
647-
_PQsetTraceFlags.argtypes = [PGconn_ptr, c_int]
648-
_PQsetTraceFlags.restype = None
649-
650-
651-
def PQsetTraceFlags(pgconn: PGconn_struct, flags: int) -> None:
652-
if not _PQsetTraceFlags:
653-
raise NotSupportedError(
654-
"PQsetTraceFlags requires libpq from PostgreSQL 14,"
655-
f" {libpq_version} available instead"
656-
)
657-
658-
_PQsetTraceFlags(pgconn, flags)
659-
603+
PQsetTraceFlags = pq.PQsetTraceFlags
604+
PQsetTraceFlags.argtypes = [PGconn_ptr, c_int]
605+
PQsetTraceFlags.restype = None
606+
else:
607+
PQsetTraceFlags = not_supported_before("PQsetTraceFlags", 14)
660608

661609
PQuntrace = pq.PQuntrace
662610
PQuntrace.argtypes = [PGconn_ptr]
@@ -669,28 +617,16 @@ def PQsetTraceFlags(pgconn: PGconn_struct, flags: int) -> None:
669617
PQfreemem.restype = None
670618

671619
if libpq_version >= 100000:
672-
_PQencryptPasswordConn = pq.PQencryptPasswordConn
673-
_PQencryptPasswordConn.argtypes = [
620+
PQencryptPasswordConn = pq.PQencryptPasswordConn
621+
PQencryptPasswordConn.argtypes = [
674622
PGconn_ptr,
675623
c_char_p,
676624
c_char_p,
677625
c_char_p,
678626
]
679-
_PQencryptPasswordConn.restype = POINTER(c_char)
680-
681-
682-
def PQencryptPasswordConn(
683-
pgconn: PGconn_struct, passwd: bytes, user: bytes, algorithm: bytes
684-
) -> Optional[bytes]:
685-
if not _PQencryptPasswordConn:
686-
raise NotSupportedError(
687-
"PQencryptPasswordConn requires libpq from PostgreSQL 10,"
688-
f" {libpq_version} available instead"
689-
)
690-
691-
rv: Optional[bytes] = _PQencryptPasswordConn(pgconn, passwd, user, algorithm)
692-
return rv
693-
627+
PQencryptPasswordConn.restype = POINTER(c_char)
628+
else:
629+
PQencryptPasswordConn = not_supported_before("PQencryptPasswordConn", 10)
694630

695631
PQmakeEmptyPGresult = pq.PQmakeEmptyPGresult
696632
PQmakeEmptyPGresult.argtypes = [PGconn_ptr, c_int]
@@ -711,82 +647,33 @@ def PQencryptPasswordConn(
711647

712648
# 34.5 Pipeline Mode
713649

714-
_PQpipelineStatus = None
715-
_PQenterPipelineMode = None
716-
_PQexitPipelineMode = None
717-
_PQpipelineSync = None
718-
_PQsendFlushRequest = None
719-
720650
if libpq_version >= 140000:
721-
_PQpipelineStatus = pq.PQpipelineStatus
722-
_PQpipelineStatus.argtypes = [PGconn_ptr]
723-
_PQpipelineStatus.restype = c_int
724-
725-
_PQenterPipelineMode = pq.PQenterPipelineMode
726-
_PQenterPipelineMode.argtypes = [PGconn_ptr]
727-
_PQenterPipelineMode.restype = c_int
728-
729-
_PQexitPipelineMode = pq.PQexitPipelineMode
730-
_PQexitPipelineMode.argtypes = [PGconn_ptr]
731-
_PQexitPipelineMode.restype = c_int
732-
733-
_PQpipelineSync = pq.PQpipelineSync
734-
_PQpipelineSync.argtypes = [PGconn_ptr]
735-
_PQpipelineSync.restype = c_int
736-
737-
_PQsendFlushRequest = pq.PQsendFlushRequest
738-
_PQsendFlushRequest.argtypes = [PGconn_ptr]
739-
_PQsendFlushRequest.restype = c_int
740-
741-
742-
def PQpipelineStatus(pgconn: PGconn_struct) -> int:
743-
if not _PQpipelineStatus:
744-
raise NotSupportedError(
745-
"PQpipelineStatus requires libpq from PostgreSQL 14,"
746-
f" {libpq_version} available instead"
747-
)
748-
rv: int = _PQpipelineStatus(pgconn)
749-
return rv
750-
751-
752-
def PQenterPipelineMode(pgconn: PGconn_struct) -> int:
753-
if not _PQenterPipelineMode:
754-
raise NotSupportedError(
755-
"PQenterPipelineMode requires libpq from PostgreSQL 14,"
756-
f" {libpq_version} available instead"
757-
)
758-
rv: int = _PQenterPipelineMode(pgconn)
759-
return rv
760-
761-
762-
def PQexitPipelineMode(pgconn: PGconn_struct) -> int:
763-
if not _PQexitPipelineMode:
764-
raise NotSupportedError(
765-
"PQexitPipelineMode requires libpq from PostgreSQL 14,"
766-
f" {libpq_version} available instead"
767-
)
768-
rv: int = _PQexitPipelineMode(pgconn)
769-
return rv
770-
771-
772-
def PQpipelineSync(pgconn: PGconn_struct) -> int:
773-
if not _PQpipelineSync:
774-
raise NotSupportedError(
775-
"PQpipelineSync requires libpq from PostgreSQL 14,"
776-
f" {libpq_version} available instead"
777-
)
778-
rv: int = _PQpipelineSync(pgconn)
779-
return rv
780-
781-
782-
def PQsendFlushRequest(pgconn: PGconn_struct) -> int:
783-
if not _PQsendFlushRequest:
784-
raise NotSupportedError(
785-
"PQsendFlushRequest requires libpq from PostgreSQL 14,"
786-
f" {libpq_version} available instead"
787-
)
788-
rv: int = _PQsendFlushRequest(pgconn)
789-
return rv
651+
PQpipelineStatus = pq.PQpipelineStatus
652+
PQpipelineStatus.argtypes = [PGconn_ptr]
653+
PQpipelineStatus.restype = c_int
654+
655+
PQenterPipelineMode = pq.PQenterPipelineMode
656+
PQenterPipelineMode.argtypes = [PGconn_ptr]
657+
PQenterPipelineMode.restype = c_int
658+
659+
PQexitPipelineMode = pq.PQexitPipelineMode
660+
PQexitPipelineMode.argtypes = [PGconn_ptr]
661+
PQexitPipelineMode.restype = c_int
662+
663+
PQpipelineSync = pq.PQpipelineSync
664+
PQpipelineSync.argtypes = [PGconn_ptr]
665+
PQpipelineSync.restype = c_int
666+
667+
PQsendFlushRequest = pq.PQsendFlushRequest
668+
PQsendFlushRequest.argtypes = [PGconn_ptr]
669+
PQsendFlushRequest.restype = c_int
670+
671+
else:
672+
PQpipelineStatus = not_supported_before("PQpipelineStatus", 14)
673+
PQenterPipelineMode = not_supported_before("PQenterPipelineMode", 14)
674+
PQexitPipelineMode = not_supported_before("PQexitPipelineMode", 14)
675+
PQpipelineSync = not_supported_before("PQpipelineSync", 14)
676+
PQsendFlushRequest = not_supported_before("PQsendFlushRequest", 14)
790677

791678

792679
# 33.18. SSL Support

0 commit comments

Comments
 (0)