From 3d12ed6e4a4905cecaa88837224e00400e06331e Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 17 Apr 2020 02:18:36 +1200 Subject: [PATCH] Pq fixtures in their own module, report the implementation being tested. --- tests/conftest.py | 6 +++- tests/fix_db.py | 74 --------------------------------------- tests/fix_pq.py | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 75 deletions(-) create mode 100644 tests/fix_pq.py diff --git a/tests/conftest.py b/tests/conftest.py index aa0b4daf4..9cb9d95d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1,5 @@ -pytest_plugins = ("tests.fix_async", "tests.fix_db") +pytest_plugins = ( + "tests.fix_async", + "tests.fix_db", + "tests.fix_pq", +) diff --git a/tests/fix_db.py b/tests/fix_db.py index 05743e382..8ac7cf3c8 100644 --- a/tests/fix_db.py +++ b/tests/fix_db.py @@ -1,6 +1,4 @@ import os -import re -import operator import pytest @@ -15,78 +13,6 @@ def pytest_addoption(parser): ) -def pytest_report_header(config): - try: - from psycopg3 import pq - - return f"libpq available: {pq.version()}" - except Exception: - # you will die of something else - pass - - -def pytest_configure(config): - # register libpq marker - config.addinivalue_line( - "markers", - "libpq(version_expr): run the test only with matching libpq" - " (e.g. '>= 10', '< 9.6')", - ) - - -@pytest.fixture -def pq(request): - """The libpq module wrapper to test.""" - from psycopg3 import pq - - for m in request.node.iter_markers(name="libpq"): - check_libpq_version(pq.version(), m.args) - - return pq - - -def check_libpq_version(got, want): - # convert 90603 to (9, 6, 3), 120003 to (12, 0, 3) - got, got_fix = divmod(got, 100) - got_maj, got_min = divmod(got, 100) - if got_maj >= 10: - got = (got_maj, got_fix) - else: - got = (got_maj, got_min, got_fix) - - # Parse a spec like "> 9.6" - if len(want) != 1: - pytest.fail("libpq marker doesn't specify a version") - want = want[0] - m = re.match( - r"^\s*(>=|<=|>|<)\s*(?:(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?\s*$", want - ) - if m is None: - pytest.fail(f"bad libpq spec: {want}") - - # convert "9.6" into (9, 6, 0), "10.3" into (10, 0, 3) - want_maj = int(m.group(2)) - want_min = int(m.group(3) or "0") - want_fix = int(m.group(4) or "0") - if want_maj >= 10: - if want_fix: - pytest.fail(f"bad libpq version in {want}") - want = (want_maj, want_min) - else: - want = (want_maj, want_min, want_fix) - - op = getattr( - operator, {">=": "ge", "<=": "le", ">": "gt", "<": "lt"}[m.group(1)] - ) - - if not op(got, want): - revops = {">=": "<", "<=": ">", ">": "<=", "<": ">="} - pytest.skip( - f"skipping test: libpq loaded is {'.'.join(map(str, got))}" - f" {revops[m.group(1)]} {'.'.join(map(str, want))}" - ) - - @pytest.fixture(scope="session") def dsn(request): """Return the dsn used to connect to the `--test-dsn` database.""" diff --git a/tests/fix_pq.py b/tests/fix_pq.py new file mode 100644 index 000000000..929d762a3 --- /dev/null +++ b/tests/fix_pq.py @@ -0,0 +1,88 @@ +import re +import operator +import pytest + + +def pytest_report_header(config): + try: + from psycopg3 import pq + + return [ + f"libpq available: {pq.version()}", + f"libpq wrapper implementation: {pq.__impl__}", + ] + except Exception: + # you will die of something else + pass + + +def pytest_configure(config): + # register libpq marker + config.addinivalue_line( + "markers", + "libpq(version_expr): run the test only with matching libpq" + " (e.g. '>= 10', '< 9.6')", + ) + + +@pytest.fixture +def pq(request): + """The libpq module wrapper to test.""" + from psycopg3 import pq + + for m in request.node.iter_markers(name="libpq"): + check_libpq_version(pq.version(), m.args) + + return pq + + +def check_libpq_version(got, want): + """ + Verify if the libpq version is a version accepted. + + This function is called on the tests marked with something like:: + + @pytest.mark.libpq(">= 12") + + and skips the test if the requested version doesn't match what's loaded. + + """ + # convert 90603 to (9, 6, 3), 120003 to (12, 0, 3) + got, got_fix = divmod(got, 100) + got_maj, got_min = divmod(got, 100) + if got_maj >= 10: + got = (got_maj, got_fix) + else: + got = (got_maj, got_min, got_fix) + + # Parse a spec like "> 9.6" + if len(want) != 1: + pytest.fail("libpq marker doesn't specify a version") + want = want[0] + m = re.match( + r"^\s*(>=|<=|>|<)\s*(?:(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?\s*$", want + ) + if m is None: + pytest.fail(f"bad libpq spec: {want}") + + # convert "9.6" into (9, 6, 0), "10.3" into (10, 0, 3) + want_maj = int(m.group(2)) + want_min = int(m.group(3) or "0") + want_fix = int(m.group(4) or "0") + if want_maj >= 10: + if want_fix: + pytest.fail(f"bad libpq version in {want}") + want = (want_maj, want_min) + else: + want = (want_maj, want_min, want_fix) + + op = getattr( + operator, {">=": "ge", "<=": "le", ">": "gt", "<": "lt"}[m.group(1)] + ) + + if not op(got, want): + revops = {">=": "<", "<=": ">", ">": "<=", "<": ">="} + pytest.skip( + f"skipping test: libpq loaded is {'.'.join(map(str, got))}" + f" {revops[m.group(1)]} {'.'.join(map(str, want))}" + ) -- 2.47.2