From abf33d3160d9007b90dccfe4776e7cda639899db Mon Sep 17 00:00:00 2001 From: jomae Date: Sun, 27 Oct 2024 21:14:00 +0000 Subject: [PATCH 1/2] 1.6.1dev: fix libpq version detection in postgres_backend.py (closes #13803) Patch by BtbN. git-svn-id: http://trac.edgewall.org/intertrac/log:/branches/1.6-stable@17861 af82e41b-90c4-0310-8c96-b1721e28e2e2 --- trac/db/postgres_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py index 162a714937..4dad6c3e14 100644 --- a/trac/db/postgres_backend.py +++ b/trac/db/postgres_backend.py @@ -62,7 +62,7 @@ '''.encode('utf-8'), _f.read(), re.VERBOSE) if _match: - _libpq_pathname = _match.group(1) + _libpq_pathname = _match.group(1).decode('utf-8') else: if re.search(r'\0libpq\.dll\0'.encode('utf-8'), _f.read(), re.IGNORECASE): From ff9f2448dbf9df6fd27e50ca81dd2a546d8f9800 Mon Sep 17 00:00:00 2001 From: jomae Date: Sun, 27 Oct 2024 22:14:27 +0000 Subject: [PATCH 2/2] 1.6.1dev: use `psycopg2.extensions.libpq_version()` to retrieve the client's version if available (refs #13803) git-svn-id: http://trac.edgewall.org/intertrac/log:/branches/1.6-stable@17862 af82e41b-90c4-0310-8c96-b1721e28e2e2 --- trac/db/postgres_backend.py | 75 +++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py index 4dad6c3e14..ad5885361d 100644 --- a/trac/db/postgres_backend.py +++ b/trac/db/postgres_backend.py @@ -44,32 +44,7 @@ register_type(UNICODE) register_adapter(Markup, lambda markup: QuotedString(str(markup))) register_adapter(type(empty), lambda empty: AsIs("''")) - psycopg2_version = get_pkginfo(psycopg).get('version', - psycopg.__version__) - _libpq_pathname = None - if not hasattr(psycopg, 'libpq_version'): - # search path of libpq only if it is dynamically linked - _f = _match = None - try: - with open(psycopg._psycopg.__file__, 'rb') as _f: - if os.name != 'nt': - _match = re.search( - r''' - \0( - (?:/[^/\0]+)*/? - libpq\.(?:so\.[0-9]+|[0-9]+\.dylib) - )\0 - '''.encode('utf-8'), - _f.read(), re.VERBOSE) - if _match: - _libpq_pathname = _match.group(1).decode('utf-8') - else: - if re.search(r'\0libpq\.dll\0'.encode('utf-8'), _f.read(), - re.IGNORECASE): - _libpq_pathname = find_library('libpq') - except AttributeError: - pass - del _f, _match + psycopg2_version = get_pkginfo(psycopg).get('version', psycopg.__version__) _like_escape_re = re.compile(r'([/_%])') @@ -94,6 +69,36 @@ def quote(value): for name, value in dsn.items() if value) +def _get_client_version(): + if hasattr(psycopg2.extensions, 'libpq_version'): # psycopg2 2.7+ + return psycopg2.extensions.libpq_version() + + if hasattr(psycopg, 'libpq_version'): + return psycopg.libpq_version() + + # search path of libpq only if it is dynamically linked + libpq_path = None + with open(psycopg._psycopg.__file__, 'rb') as f: + data = f.read() + if os.name != 'nt': + match = re.search( + br''' + \0( + (?:/[^/\0]+)*/? + libpq\.(?:so\.[0-9]+|[0-9]+\.dylib) + )\0 + ''', + data, re.VERBOSE) + if match: + libpq_path = str(match.group(1), 'utf-8') + else: + if re.search(br'\0libpq\.dll\0', data, re.IGNORECASE): + libpq_path = find_library('libpq') + if libpq_path: + lib = ctypes.CDLL(libpq_path) + return lib.PQlibVersion() + + def _quote(identifier): return '"%s"' % identifier.replace('"', '""') @@ -291,17 +296,13 @@ def get_system_info(self): @lazy def _client_version(self): - version = None - if hasattr(psycopg, 'libpq_version'): - version = psycopg.libpq_version() - elif _libpq_pathname: - try: - lib = ctypes.CDLL(_libpq_pathname) - version = lib.PQlibVersion() - except Exception as e: - self.log.warning("Exception caught while retrieving libpq's " - "version%s", - exception_to_unicode(e, traceback=True)) + try: + version = _get_client_version() + except Exception as e: + self.log.warning("Exception caught while retrieving libpq's " + "version%s", + exception_to_unicode(e, traceback=True)) + version = None return _version_tuple(version) def _pgdump_version(self):