File: test_capabilities.py

package info (click to toggle)
psycopg3 3.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,836 kB
  • sloc: python: 46,657; sh: 403; ansic: 149; makefile: 73
file content (99 lines) | stat: -rw-r--r-- 2,959 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import re

import pytest

from psycopg import _cmodule, pq

try:
    from psycopg import Capabilities, NotSupportedError, capabilities
except ImportError:
    # Allow to import the module with Psycopg 3.1
    pass

caps = [
    ("has_full_protocol_version", "pq.PGconn.full_protocol_version()", 18),
    ("has_encrypt_password", "pq.PGconn.encrypt_password()", 10),
    ("has_hostaddr", "Connection.info.hostaddr", 12),
    ("has_pipeline", "Connection.pipeline()", 14),
    ("has_set_trace_flags", "PGconn.set_trace_flags()", 14),
    ("has_used_gssapi", "PGconn.used_gssapi", 16),
    ("has_cancel_safe", "Connection.cancel_safe()", 17),
    ("has_stream_chunked", "Cursor.stream() with 'size' parameter greater than 1", 17),
    ("has_send_close_prepared", "PGconn.send_close_prepared()", 17),
]


@pytest.mark.parametrize(
    "method_name",
    [
        pytest.param(method_name, marks=pytest.mark.libpq(f">= {min_ver}"))
        for method_name, _, min_ver in caps
    ],
)
def test_has_capability(method_name):
    method = getattr(capabilities, method_name)
    assert method()
    assert method(check=True)


@pytest.mark.parametrize(
    "method_name, label",
    [
        pytest.param(method_name, label, marks=pytest.mark.libpq(f"< {min_ver}"))
        for method_name, label, min_ver in caps
    ],
)
def test_no_capability(method_name, label):
    method = getattr(capabilities, method_name)
    assert not method()
    with pytest.raises(NotSupportedError, match=f"'{re.escape(label)}'"):
        method(check=True)


def test_build_or_import_msg(monkeypatch):
    monkeypatch.setattr(pq, "version", lambda: 140000)
    monkeypatch.setattr(pq, "__build_version__", 139999)
    with pytest.raises(NotSupportedError, match=r"built with libpq version 13\.99\.99"):
        Capabilities().has_pipeline(check=True)

    monkeypatch.setattr(pq, "version", lambda: 139999)
    with pytest.raises(
        NotSupportedError, match=r"client libpq version \(.*\) is 13\.99\.99"
    ):
        Capabilities().has_pipeline(check=True)


def test_impl_build_error(monkeypatch):
    monkeypatch.setattr(pq, "__build_version__", 139999)
    monkeypatch.setattr(pq, "version", lambda: 139999)
    if pq.__impl__ == "binary":
        ver = _cmodule.__version__
        assert ver
        msg = "(imported from the psycopg[binary] package version {ver})"
    else:
        msg = "(imported from system libraries)"
        with pytest.raises(NotSupportedError, match=re.escape(msg)):
            Capabilities().has_pipeline(check=True)


def test_caching(monkeypatch):

    version = 150000

    caps = Capabilities()
    called = 0

    def ver():
        nonlocal called
        called += 1
        return version

    monkeypatch.setattr(pq, "version", ver)
    monkeypatch.setattr(pq, "__build_version__", version)

    caps.has_pipeline()
    assert called == 1
    caps.has_pipeline()
    assert called == 1
    caps.has_hostaddr()
    assert called == 2