]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Allow adapter protocols tests to run on Python 3.6
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 11 Jul 2021 02:27:20 +0000 (04:27 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 11 Jul 2021 12:43:58 +0000 (14:43 +0200)
tests/adapters_example.py [new file with mode: 0644]
tests/test_adapt.py
tests/test_typing.py
tests/typing_example.py

diff --git a/tests/adapters_example.py b/tests/adapters_example.py
new file mode 100644 (file)
index 0000000..57ff380
--- /dev/null
@@ -0,0 +1,51 @@
+from typing import Optional, Tuple, Union
+
+from psycopg import pq
+from psycopg.proto import Dumper, Loader, AdaptContext, PyFormat, Buffer
+
+
+def f() -> None:
+    d: Dumper = MyStrDumper(str, None)
+    assert d.dump("abc") == b"abcabc"
+    assert d.quote("abc") == b"'abcabc'"
+
+    lo: Loader = MyTextLoader(0, None)
+    assert lo.load(b"abc") == "abcabc"
+
+
+class MyStrDumper:
+    format = pq.Format.TEXT
+
+    def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+        self._cls = cls
+        self.oid = 25  # text
+
+    def dump(self, obj: str) -> bytes:
+        return (obj * 2).encode("utf-8")
+
+    def quote(self, obj: str) -> bytes:
+        value = self.dump(obj)
+        esc = pq.Escaping()
+        return b"'%s'" % esc.escape_string(value.replace(b"h", b"q"))
+
+    def get_key(self, obj: str, format: PyFormat) -> type:
+        return self._cls
+
+    def upgrade(self, obj: str, format: PyFormat) -> "MyStrDumper":
+        return self
+
+
+class MyTextLoader:
+    format = pq.Format.TEXT
+
+    def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+        pass
+
+    def load(self, data: Buffer) -> str:
+        return (bytes(data) * 2).decode("utf-8")
+
+
+# This should be the definition of psycopg.adapt.DumperKey, but mypy doesn't
+# support recursive types. When it will, this statement will give an error
+# (unused type: ignore) so we can fix our definition.
+_DumperKey = Union[type, Tuple[Union[type, "_DumperKey"]]]  # type: ignore
index 9a5f1b6891e4dad8f332d44c720d29c2a2c10b93..3f9d93c5b42640b5fd504a3f5cee2ac98195583b 100644 (file)
@@ -108,7 +108,7 @@ def test_subclass_dumper(conn):
 def test_dumper_protocol(conn):
 
     # This class doesn't inherit from adapt.Dumper but passes a mypy check
-    from .typing_example import MyStrDumper
+    from .adapters_example import MyStrDumper
 
     conn.adapters.register_dumper(str, MyStrDumper)
     cur = conn.execute("select %s", ["hello"])
@@ -121,7 +121,7 @@ def test_dumper_protocol(conn):
 def test_loader_protocol(conn):
 
     # This class doesn't inherit from adapt.Loader but passes a mypy check
-    from .typing_example import MyTextLoader
+    from .adapters_example import MyTextLoader
 
     conn.adapters.register_loader("text", MyTextLoader)
     cur = conn.execute("select 'hello'::text")
index 365ae542b1bf9e6604d9b0b0da25878d43488516..3ef42067384b9486f2ff8e56e84d2400b6fd2ecc 100644 (file)
@@ -6,9 +6,20 @@ import pytest
 
 
 @pytest.mark.slow
-@pytest.mark.skipif(sys.version_info < (3, 7), reason="no future annotations")
-def test_typing_example(mypy):
-    cp = mypy.run("tests/typing_example.py")
+@pytest.mark.parametrize(
+    "filename",
+    [
+        "tests/adapters_example.py",
+        pytest.param(
+            "tests/typing_example.py",
+            marks=pytest.mark.skipif(
+                sys.version_info < (3, 7), reason="no future annotations"
+            ),
+        ),
+    ],
+)
+def test_typing_example(mypy, filename):
+    cp = mypy.run(filename)
     errors = cp.stdout.decode("utf8", "replace").splitlines()
     assert not errors
     assert cp.returncode == 0
index 6746125faf4a0e767d5a70ca74ca660381739540..b0d4c3e611fc48397eb22a93df73e86771cdb30e 100644 (file)
@@ -3,11 +3,9 @@
 from __future__ import annotations
 
 from dataclasses import dataclass
-from typing import Any, Callable, Optional, Sequence, Tuple, Union
+from typing import Any, Callable, Optional, Sequence, Tuple
 
 from psycopg import AnyCursor, Connection, Cursor, ServerCursor, connect
-from psycopg import pq
-from psycopg.proto import Dumper, Loader, AdaptContext, PyFormat, Buffer
 
 
 def int_row_factory(cursor: AnyCursor[int]) -> Callable[[Sequence[int]], int]:
@@ -87,50 +85,3 @@ def check_row_factory_connection() -> None:
         cur3.execute("select 42")
         r3 = cur3.fetchone()
         r3 and len(r3)
-
-
-def f() -> None:
-    d: Dumper = MyStrDumper(str, None)
-    assert d.dump("abc") == b"abcabc"
-    assert d.quote("abc") == b"'abcabc'"
-
-    lo: Loader = MyTextLoader(0, None)
-    assert lo.load(b"abc") == "abcabc"
-
-
-class MyStrDumper:
-    format = pq.Format.TEXT
-
-    def __init__(self, cls: type, context: Optional[AdaptContext] = None):
-        self._cls = cls
-        self.oid = 25  # text
-
-    def dump(self, obj: str) -> bytes:
-        return (obj * 2).encode("utf-8")
-
-    def quote(self, obj: str) -> bytes:
-        value = self.dump(obj)
-        esc = pq.Escaping()
-        return b"'%s'" % esc.escape_string(value.replace(b"h", b"q"))
-
-    def get_key(self, obj: str, format: PyFormat) -> type:
-        return self._cls
-
-    def upgrade(self, obj: str, format: PyFormat) -> "MyStrDumper":
-        return self
-
-
-class MyTextLoader:
-    format = pq.Format.TEXT
-
-    def __init__(self, oid: int, context: Optional[AdaptContext] = None):
-        pass
-
-    def load(self, data: Buffer) -> str:
-        return (bytes(data) * 2).decode("utf-8")
-
-
-# This should be the definition of psycopg.adapt.DumperKey, but mypy doesn't
-# support recursive types. When it will, this statement will give an error
-# (unused type: ignore) so we can fix our definition.
-_DumperKey = Union[type, Tuple[Union[type, "_DumperKey"]]]  # type: ignore