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
@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:
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]
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
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
@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 = {
@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)
@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)
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
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"])
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")