def __init__(self, cls: type, context: Optional[AdaptContext] = None):
super().__init__(cls, context)
self._tx = Transformer(context)
- fmt = Pg3Format.from_pq(self.format)
- self.sub_dumper = self._tx.get_dumper("", fmt)
- self.sub_oid = TEXT_OID
+ self.sub_dumper: Optional[Dumper] = None
def get_key(self, obj: List[Any], format: Pg3Format) -> Tuple[type, ...]:
item = self._find_list_element(obj)
def upgrade(self, obj: List[Any], format: Pg3Format) -> "BaseListDumper":
item = self._find_list_element(obj)
if item is None:
+ # Empty lists can only be dumped as text if the type is unknown.
return ListDumper(self.cls, self._tx)
sd = self._tx.get_dumper(item, format)
dumper.sub_dumper = sd
# We consider an array of unknowns as unknown, so we can dump empty
- # lists or lists containing only None elements. However Postgres won't
- # take unknown for element oid (in binary; in text it doesn't matter)
+ # lists or lists containing only None elements.
if sd.oid != INVALID_OID:
dumper.oid = self._get_array_oid(sd.oid)
- dumper.sub_oid = sd.oid
else:
dumper.oid = INVALID_OID
- dumper.sub_oid = TEXT_OID
return dumper
if isinstance(item, list):
dump_list(item)
elif item is not None:
- ad = self.sub_dumper.dump(item)
+ # If we get here, the sub_dumper must have been set
+ ad = self.sub_dumper.dump(item) # type: ignore[union-attr]
if self._re_needs_quotes.search(ad):
ad = (
b'"' + self._re_esc.sub(br"\\\1", bytes(ad)) + b'"'
format = pq.Format.BINARY
def dump(self, obj: List[Any]) -> bytes:
+ # Postgres won't take unknown for element oid: fall back on text
+ sub_oid = self.sub_dumper and self.sub_dumper.oid or TEXT_OID
+
if not obj:
- return _struct_head.pack(0, 0, self.sub_oid)
+ return _struct_head.pack(0, 0, sub_oid)
data: List[bytes] = [b"", b""] # placeholders to avoid a resize
dims: List[int] = []
if dim == len(dims) - 1:
for item in L:
if item is not None:
- ad = self.sub_dumper.dump(item)
+ # If we get here, the sub_dumper must have been set
+ ad = self.sub_dumper.dump(item) # type: ignore[union-attr]
data.append(_struct_len.pack(len(ad)))
data.append(ad)
else:
dump_list(obj, 0)
- data[0] = _struct_head.pack(len(dims), hasnull, self.sub_oid)
+ data[0] = _struct_head.pack(len(dims), hasnull, sub_oid)
data[1] = b"".join(_struct_dim.pack(dim, 1) for dim in dims)
return b"".join(data)
fmt_in = Format.from_pq(fmt_out)
dint = t.get_dumper([0], fmt_in)
assert dint.oid == builtins["int2"].array_oid
- assert dint.sub_oid == builtins["int2"].oid
+ assert dint.sub_dumper.oid == builtins["int2"].oid
dstr = t.get_dumper([""], fmt_in)
- assert dstr.oid == (
- builtins["text"].array_oid if fmt_in == Format.BINARY else 0
- )
- assert dstr.sub_oid == builtins["text"].oid
+ if fmt_in == Format.BINARY:
+ assert dstr.oid == builtins["text"].array_oid
+ assert dstr.sub_dumper.oid == builtins["text"].oid
+ else:
+ assert dstr.oid == 0
+ assert dstr.sub_dumper.oid == 0
+
assert dstr is not dint
assert t.get_dumper([1], fmt_in) is dint