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