1#!/usr/bin/env python3 2""" 3PostgreSQL database adapter for Python - optimisation package 4""" 5 6# Copyright (C) 2020-2021 The Psycopg Team 7 8import os 9import re 10import sys 11import subprocess as sp 12 13from setuptools import setup, Extension 14from distutils.command.build_ext import build_ext 15from distutils import log 16 17# Move to the directory of setup.py: executing this file from another location 18# (e.g. from the project root) will fail 19here = os.path.abspath(os.path.dirname(__file__)) 20if os.path.abspath(os.getcwd()) != here: 21 os.chdir(here) 22 23with open("psycopg_c/version.py") as f: 24 data = f.read() 25 m = re.search(r"""(?m)^__version__\s*=\s*['"]([^'"]+)['"]""", data) 26 if m is None: 27 raise Exception(f"cannot find version in {f.name}") 28 version = m.group(1) 29 30 31def get_config(what: str) -> str: 32 pg_config = "pg_config" 33 try: 34 out = sp.run([pg_config, f"--{what}"], stdout=sp.PIPE, check=True) 35 except Exception as e: 36 log.error(f"couldn't run {pg_config!r} --{what}: %s", e) 37 raise 38 else: 39 return out.stdout.strip().decode() 40 41 42class psycopg_build_ext(build_ext): 43 def finalize_options(self) -> None: 44 self._setup_ext_build() 45 super().finalize_options() 46 47 def _setup_ext_build(self) -> None: 48 cythonize = None 49 50 # In the sdist there are not .pyx, only c, so we don't need Cython 51 # Otherwise Cython is a requirement and is be used to compile pyx to c 52 if os.path.exists("psycopg_c/_psycopg.pyx"): 53 from Cython.Build import cythonize 54 55 # Add include and lib dir for the libpq. 56 includedir = get_config("includedir") 57 libdir = get_config("libdir") 58 for ext in self.distribution.ext_modules: 59 ext.include_dirs.append(includedir) 60 ext.library_dirs.append(libdir) 61 62 if sys.platform == "win32": 63 # For __imp_htons and others 64 ext.libraries.append("ws2_32") 65 66 if cythonize is not None: 67 for ext in self.distribution.ext_modules: 68 for i in range(len(ext.sources)): 69 base, fext = os.path.splitext(ext.sources[i]) 70 if fext == ".c" and os.path.exists(base + ".pyx"): 71 ext.sources[i] = base + ".pyx" 72 73 self.distribution.ext_modules = cythonize( 74 self.distribution.ext_modules, 75 language_level=3, 76 compiler_directives={ 77 "always_allow_keywords": False, 78 }, 79 annotate=False, # enable to get an html view of the C module 80 ) 81 else: 82 self.distribution.ext_modules = [pgext, pqext] 83 84 85# MSVC requires an explicit "libpq" 86libpq = "pq" if sys.platform != "win32" else "libpq" 87 88# Some details missing, to be finished by psycopg_build_ext.finalize_options 89pgext = Extension( 90 "psycopg_c._psycopg", 91 [ 92 "psycopg_c/_psycopg.c", 93 "psycopg_c/types/numutils.c", 94 ], 95 libraries=[libpq], 96 include_dirs=[], 97) 98 99pqext = Extension( 100 "psycopg_c.pq", 101 ["psycopg_c/pq.c"], 102 libraries=[libpq], 103 include_dirs=[], 104) 105 106setup( 107 version=version, 108 ext_modules=[pgext, pqext], 109 cmdclass={"build_ext": psycopg_build_ext}, 110) 111