1{
2 lib,
3 stdenv,
4 buildPythonPackage,
5 fetchFromGitHub,
6 fetchurl,
7 replaceVars,
8
9 # build
10 libpq,
11 setuptools,
12
13 # propagates
14 typing-extensions,
15
16 # psycopg-c
17 cython,
18 tomli,
19
20 # docs
21 furo,
22 shapely,
23 sphinxHook,
24 sphinx-autodoc-typehints,
25
26 # tests
27 anyio,
28 pproxy,
29 pytest-randomly,
30 pytestCheckHook,
31 postgresql,
32 postgresqlTestHook,
33}:
34
35let
36 pname = "psycopg";
37 version = "3.2.10";
38
39 src = fetchFromGitHub {
40 owner = "psycopg";
41 repo = "psycopg";
42 tag = version;
43 hash = "sha256-ZvqhvjDhrZ7uKi9fE/UYRaJblmfXXH6pYoUZ5u7cOu0=";
44 };
45
46 patches = [
47 (replaceVars ./ctypes.patch {
48 libpq = "${libpq}/lib/libpq${stdenv.hostPlatform.extensions.sharedLibrary}";
49 libc = "${stdenv.cc.libc}/lib/libc.so.6";
50 })
51 ];
52
53 baseMeta = {
54 changelog = "https://github.com/psycopg/psycopg/blob/${version}/docs/news.rst#current-release";
55 homepage = "https://github.com/psycopg/psycopg";
56 license = lib.licenses.lgpl3Plus;
57 maintainers = with lib.maintainers; [ hexa ];
58 };
59
60 psycopg-c = buildPythonPackage {
61 pname = "${pname}-c";
62 inherit version src;
63 format = "pyproject";
64
65 # apply patches to base repo
66 inherit patches;
67
68 # move into source root after patching
69 postPatch = ''
70 cd psycopg_c
71 '';
72
73 nativeBuildInputs = [
74 cython
75 libpq.pg_config
76 setuptools
77 tomli
78 ];
79
80 buildInputs = [
81 libpq
82 ];
83
84 # tested in psycopg
85 doCheck = false;
86
87 meta = baseMeta // {
88 description = "C optimisation distribution for Psycopg";
89 };
90 };
91
92 psycopg-pool = buildPythonPackage {
93 pname = "${pname}-pool";
94 inherit version src;
95 format = "setuptools";
96
97 # apply patches to base repo
98 inherit patches;
99
100 # move into source root after patching
101 postPatch = ''
102 cd psycopg_pool
103 '';
104
105 propagatedBuildInputs = [ typing-extensions ];
106
107 # tested in psycopg
108 doCheck = false;
109
110 meta = baseMeta // {
111 description = "Connection Pool for Psycopg";
112 };
113 };
114in
115
116buildPythonPackage rec {
117 inherit pname version src;
118 pyproject = true;
119
120 outputs = [
121 "out"
122 ]
123 ++ lib.optionals (stdenv.hostPlatform == stdenv.buildPlatform) [
124 "doc"
125 ];
126
127 sphinxRoot = "../docs";
128
129 # Introduce this file necessary for the docs build via environment var
130 LIBPQ_DOCS_FILE = fetchurl {
131 url = "https://raw.githubusercontent.com/postgres/postgres/496a1dc44bf1261053da9b3f7e430769754298b4/doc/src/sgml/libpq.sgml";
132 hash = "sha256-JwtCngkoi9pb0pqIdNgukY8GbG5pUDZvrGAHZqjFOw4";
133 };
134
135 inherit patches;
136
137 # only move to sourceRoot after patching, makes patching easier
138 postPatch = ''
139 cd psycopg
140 '';
141
142 nativeBuildInputs = [
143 setuptools
144 ]
145 # building the docs fails with the following error when cross compiling
146 # AttributeError: module 'psycopg_c.pq' has no attribute '__impl__'
147 ++ lib.optionals (stdenv.hostPlatform == stdenv.buildPlatform) [
148 furo
149 sphinx-autodoc-typehints
150 sphinxHook
151 shapely
152 ];
153
154 propagatedBuildInputs = [
155 psycopg-c
156 typing-extensions
157 ];
158
159 pythonImportsCheck = [
160 "psycopg"
161 "psycopg_c"
162 "psycopg_pool"
163 ];
164
165 optional-dependencies = {
166 c = [ psycopg-c ];
167 pool = [ psycopg-pool ];
168 };
169
170 nativeCheckInputs = [
171 anyio
172 pproxy
173 pytest-randomly
174 pytestCheckHook
175 postgresql
176 ]
177 ++ lib.optional stdenv.hostPlatform.isLinux postgresqlTestHook
178 ++ optional-dependencies.c
179 ++ optional-dependencies.pool;
180
181 env = {
182 postgresqlEnableTCP = 1;
183 PGUSER = "psycopg";
184 PGDATABASE = "psycopg";
185 };
186
187 preCheck = ''
188 cd ..
189 ''
190 + lib.optionalString stdenv.hostPlatform.isLinux ''
191 export PSYCOPG_TEST_DSN="host=/build/run/postgresql user=$PGUSER"
192 '';
193
194 disabledTests = [
195 # don't depend on mypy for tests
196 "test_version"
197 "test_package_version"
198 # expects timeout, but we have no route in the sandbox
199 "test_connect_error_multi_hosts_each_message_preserved"
200 ];
201
202 disabledTestPaths = [
203 # Network access
204 "tests/test_dns.py"
205 "tests/test_dns_srv.py"
206 # Mypy typing test
207 "tests/test_typing.py"
208 "tests/crdb/test_typing.py"
209 ];
210
211 pytestFlags = [
212 "-ocache_dir=.cache"
213 ];
214
215 disabledTestMarks = [
216 "refcount"
217 "timing"
218 "flakey"
219 ];
220
221 postCheck = ''
222 cd psycopg
223 '';
224
225 passthru = {
226 c = psycopg-c;
227 pool = psycopg-pool;
228 };
229
230 meta = baseMeta // {
231 description = "PostgreSQL database adapter for Python";
232 };
233}