]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Dropped use of plain functions to define dumpers
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 5 Aug 2020 22:25:56 +0000 (23:25 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 23 Aug 2020 18:24:01 +0000 (19:24 +0100)
psycopg3/psycopg3/adapt.py
psycopg3/psycopg3/dbapi20.py
psycopg3/psycopg3/proto.py
psycopg3/psycopg3/transform.py
psycopg3/psycopg3/types/numeric.py
psycopg3/psycopg3/types/text.py
psycopg3_c/psycopg3_c/transform.pyx
tests/test_adapt.py

index da173d6b7dcff3f38268ec284c0c69b780e3daa7..ea70aba53205dfff46e92183c9f9cd7e8fb40d03 100644 (file)
@@ -40,13 +40,9 @@ class Dumper:
                 f"dumpers should be registered on classes, got {src} instead"
             )
 
-        if not (
-            callable(dumper)
-            or (isinstance(dumper, type) and issubclass(dumper, Dumper))
-        ):
+        if not (isinstance(dumper, type) and issubclass(dumper, Dumper)):
             raise TypeError(
-                f"dumpers should be callable or Dumper subclasses,"
-                f" got {dumper} instead"
+                f"dumpers should be Dumper subclasses, got {dumper} instead"
             )
 
         where = context.dumpers if context is not None else Dumper.globals
index 527a021594cefe1a199047083081680d29658d89..2c0763478e8dae3b98665bc5e9a70834142d5ecb 100644 (file)
@@ -51,12 +51,13 @@ class Binary:
 
 
 @Dumper.text(Binary)
-def dump_Binary(obj: Binary) -> Tuple[bytes, int]:
-    rv = obj.obj
-    if not isinstance(rv, bytes):
-        rv = bytes(rv)
+class TextBinaryDumper(Dumper):
+    def dump(self, obj: Binary) -> Tuple[bytes, int]:
+        rv = obj.obj
+        if not isinstance(rv, bytes):
+            rv = bytes(rv)
 
-    return rv, builtins["bytea"].oid
+        return rv, builtins["bytea"].oid
 
 
 def Date(year: int, month: int, day: int) -> dt.date:
index 1a4ac3140696a7ce105a98f953bb6c21a675c86e..9b84e28d4c69969c2e5f25468750d6612014213c 100644 (file)
@@ -38,7 +38,7 @@ AdaptContext = Union[None, "BaseConnection", "BaseCursor", "Transformer"]
 
 MaybeOid = Union[Optional[bytes], Tuple[Optional[bytes], int]]
 DumpFunc = Callable[[Any], MaybeOid]
-DumperType = Union[Type["Dumper"], DumpFunc]
+DumperType = Type["Dumper"]
 DumpersMap = Dict[Tuple[type, Format], DumperType]
 
 LoadFunc = Callable[[bytes], Any]
index 6ef1fca49463cdd7bdc6def18fbea7615ea588c2..e8a1c714c9268f0d602328ebe549f23e7974d591 100644 (file)
@@ -172,10 +172,7 @@ class Transformer:
 
         dumper = self.lookup_dumper(src, format)
         func: DumpFunc
-        if isinstance(dumper, type):
-            func = dumper(src, self).dump
-        else:
-            func = dumper
+        func = dumper(src, self).dump
 
         self._dump_funcs[key] = func
         return func
index a16c82b0ff43d966dff84cb962f23b063ae6f319..5c22561d5233906724363606a12651b8b83a5b4d 100644 (file)
@@ -14,6 +14,7 @@ from .oids import builtins
 
 FLOAT8_OID = builtins["float8"].oid
 NUMERIC_OID = builtins["numeric"].oid
+BOOL_OID = builtins["bool"].oid
 
 _encode = codecs.lookup("ascii").encode
 _decode = codecs.lookup("ascii").decode
@@ -27,20 +28,27 @@ _float8_struct = struct.Struct("!d")
 
 
 @Dumper.text(int)
-def dump_int(obj: int) -> Tuple[bytes, int]:
-    # We don't know the size of it, so we have to return a type big enough
-    return _encode(str(obj))[0], NUMERIC_OID
+class TextIntDumper(Dumper):
+    def dump(self, obj: int) -> Tuple[bytes, int]:
+        # We don't know the size of it, so we have to return a type big enough
+        return _encode(str(obj))[0], NUMERIC_OID
 
 
 @Dumper.text(float)
-def dump_float(obj: float) -> Tuple[bytes, int]:
-    # Float can't be bigger than this instead
-    return _encode(str(obj))[0], FLOAT8_OID
+class TextFloatDumper(Dumper):
+    def dump(self, obj: float) -> Tuple[bytes, int]:
+        # Float can't be bigger than this instead
+        return _encode(str(obj))[0], FLOAT8_OID
 
 
 @Dumper.text(Decimal)
-def dump_decimal(obj: Decimal) -> Tuple[bytes, int]:
-    return _encode(str(obj))[0], NUMERIC_OID
+class TextDecimalDumper(Dumper):
+    def dump(self, obj: Decimal) -> Tuple[bytes, int]:
+        return _encode(str(obj))[0], NUMERIC_OID
+
+    @property
+    def oid(self) -> int:
+        return NUMERIC_OID
 
 
 _bool_dump = {
@@ -54,13 +62,23 @@ _bool_binary_dump = {
 
 
 @Dumper.text(bool)
-def dump_bool(obj: bool) -> Tuple[bytes, int]:
-    return _bool_dump[obj]
+class TextBoolDumper(Dumper):
+    def dump(self, obj: bool) -> Tuple[bytes, int]:
+        return _bool_dump[obj]
+
+    @property
+    def oid(self) -> int:
+        return BOOL_OID
 
 
 @Dumper.binary(bool)
-def dump_bool_binary(obj: bool) -> Tuple[bytes, int]:
-    return _bool_binary_dump[obj]
+class BinaryBoolDumper(Dumper):
+    def dump(self, obj: bool) -> Tuple[bytes, int]:
+        return _bool_binary_dump[obj]
+
+    @property
+    def oid(self) -> int:
+        return BOOL_OID
 
 
 @Loader.text(builtins["int2"].oid)
index e3ac114b35f181664cfa466c4d6f45f1a93eb980..11a147eca995105a24f3f52c1607766e0a37cf8b 100644 (file)
@@ -95,8 +95,9 @@ class BytesDumper(Dumper):
 
 
 @Dumper.binary(bytes)
-def dump_bytes(b: bytes) -> Tuple[bytes, int]:
-    return b, BYTEA_OID
+class BinaryBytesDumper(Dumper):
+    def dump(self, b: bytes) -> Tuple[bytes, int]:
+        return b, BYTEA_OID
 
 
 @Loader.text(builtins["bytea"].oid)
index 28411b64f19f40c3bbff73bc8300ade8488fb4ce..7b438fb6c38b619d05853ec0082a480d04ed473d 100644 (file)
@@ -252,12 +252,7 @@ cdef class Transformer:
             pass
 
         dumper = self.lookup_dumper(src, format)
-        func: "DumpFunc"
-        if isinstance(dumper, type):
-            func = dumper(src, self).dump
-        else:
-            func = dumper
-
+        func = dumper(src, self).dump
         self._dump_funcs[key] = func
         return func
 
index a22c4e1ea991179bb108260f6334b81c33a66b78..6a26fc89f5a4ee8c7cde9bc2f24025882f768211 100644 (file)
@@ -25,9 +25,19 @@ def test_dump(data, format, result, type):
         assert rv == result
 
 
+def make_dumper(suffix):
+    """Create a test dumper appending a suffix to the bytes representation."""
+
+    class TestDumper(Dumper):
+        def dump(self, s):
+            return (s + suffix).encode("ascii")
+
+    return TestDumper
+
+
 def test_dump_connection_ctx(conn):
-    Dumper.register(str, lambda s: s.encode("ascii") + b"t", conn)
-    Dumper.register_binary(str, lambda s: s.encode("ascii") + b"b", conn)
+    Dumper.register(str, make_dumper("t"), conn)
+    Dumper.register_binary(str, make_dumper("b"), conn)
 
     cur = conn.cursor()
     cur.execute("select %s, %b", ["hello", "world"])
@@ -35,12 +45,12 @@ def test_dump_connection_ctx(conn):
 
 
 def test_dump_cursor_ctx(conn):
-    Dumper.register(str, lambda s: s.encode("ascii") + b"t", conn)
-    Dumper.register_binary(str, lambda s: s.encode("ascii") + b"b", conn)
+    Dumper.register(str, make_dumper("t"), conn)
+    Dumper.register_binary(str, make_dumper("b"), conn)
 
     cur = conn.cursor()
-    Dumper.register(str, lambda s: s.encode("ascii") + b"tc", cur)
-    Dumper.register_binary(str, lambda s: s.encode("ascii") + b"bc", cur)
+    Dumper.register(str, make_dumper("tc"), cur)
+    Dumper.register_binary(str, make_dumper("bc"), cur)
 
     cur.execute("select %s, %b", ["hello", "world"])
     assert cur.fetchone() == ("hellotc", "worldbc")