]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: manage None as return value of Dumper.dump()
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 19 Sep 2022 00:08:19 +0000 (01:08 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 1 Jun 2024 11:07:21 +0000 (13:07 +0200)
These are only the changes suggested by Mypy; no test added to verify
that the code paths actually work.

Only Python test fixed, no C yet.

psycopg/psycopg/adapt.py
psycopg/psycopg/types/array.py
psycopg/psycopg/types/hstore.py
psycopg/psycopg/types/range.py

index 4b33fbb672cde0c772adc54ee33d0a51daab6bfd..07b7b9a5b7e0465f106874f15c5cb75246e7a72e 100644 (file)
@@ -56,6 +56,8 @@ class Dumper(abc.Dumper, ABC):
         subclass.
         """
         value = self.dump(obj)
+        if value is None:
+            return b"NULL"
 
         if self.connection:
             esc = pq.Escaping(self.connection.pgconn)
index 3a8b1328e04f2094eea4683e4fe93c1815ebc90b..d4a5dc0b2caa68c9fb8cfcc0a65d316b02aec2cd 100644 (file)
@@ -168,11 +168,14 @@ class ListDumper(BaseListDumper):
                     dump_list(item)
                 elif item is not None:
                     ad = self._dump_item(item)
-                    if needs_quotes(ad):
-                        if not isinstance(ad, bytes):
-                            ad = bytes(ad)
-                        ad = b'"' + self._re_esc.sub(rb"\\\1", ad) + b'"'
-                    tokens.append(ad)
+                    if ad is None:
+                        tokens.append(b"NULL")
+                    else:
+                        if needs_quotes(ad):
+                            if not isinstance(ad, bytes):
+                                ad = bytes(ad)
+                            ad = b'"' + self._re_esc.sub(rb"\\\1", ad) + b'"'
+                        tokens.append(ad)
                 else:
                     tokens.append(b"NULL")
 
@@ -184,7 +187,7 @@ class ListDumper(BaseListDumper):
 
         return b"".join(tokens)
 
-    def _dump_item(self, item: Any) -> Buffer:
+    def _dump_item(self, item: Any) -> Optional[Buffer]:
         if self.sub_dumper:
             return self.sub_dumper.dump(item)
         else:
@@ -271,9 +274,10 @@ class ListBinaryDumper(BaseListDumper):
                 for item in L:
                     if item is not None:
                         # If we get here, the sub_dumper must have been set
-                        ad = self.sub_dumper.dump(item)  # type: ignore[union-attr]
-                        data.append(pack_len(len(ad)))
-                        data.append(ad)
+                        item = self.sub_dumper.dump(item)  # type: ignore[union-attr]
+                    if item is not None:
+                        data.append(pack_len(len(item)))
+                        data.append(item)
                     else:
                         hasnull = 1
                         data.append(b"\xff\xff\xff\xff")
index 5bc261f5563c0df89a1c9d283cd273bcfc7d6726..2c52f79f1ba193e49e35fb0ef92c7558ddabfb0a 100644 (file)
@@ -39,7 +39,7 @@ Hstore: TypeAlias = Dict[str, Optional[str]]
 
 
 class BaseHstoreDumper(RecursiveDumper):
-    def dump(self, obj: Hstore) -> Buffer:
+    def dump(self, obj: Hstore) -> Optional[Buffer]:
         if not obj:
             return b""
 
index 9d91f89104c20da0aea0c7648b52332268edfc43..e320e42037193cdbbd112ef99a7d20de8a7a016a 100644 (file)
@@ -5,7 +5,7 @@ Support for range types adaptation.
 # Copyright (C) 2020 The Psycopg Team
 
 import re
-from typing import Any, Callable, Dict, Generic, List, Optional, Type, Tuple
+from typing import Any, Dict, Generic, List, Optional, Type, Tuple
 from typing import cast, TYPE_CHECKING
 from decimal import Decimal
 from datetime import date, datetime
@@ -15,7 +15,7 @@ from .. import _oids
 from .. import errors as e
 from .. import postgres
 from ..pq import Format
-from ..abc import AdaptContext, Buffer, Dumper, DumperKey, Query
+from ..abc import AdaptContext, Buffer, Dumper, DumperKey, DumpFunc, LoadFunc, Query
 from ..adapt import RecursiveDumper, RecursiveLoader, PyFormat
 from .._oids import INVALID_OID, TEXT_OID
 from .._compat import cache, TypeVar
@@ -364,7 +364,7 @@ class RangeDumper(BaseRangeDumper):
         return dump_range_text(obj, dump)
 
 
-def dump_range_text(obj: Range[Any], dump: Callable[[Any], Buffer]) -> Buffer:
+def dump_range_text(obj: Range[Any], dump: DumpFunc) -> Buffer:
     if obj.isempty:
         return b"empty"
 
@@ -409,7 +409,7 @@ class RangeBinaryDumper(BaseRangeDumper):
         return dump_range_binary(obj, dump)
 
 
-def dump_range_binary(obj: Range[Any], dump: Callable[[Any], Buffer]) -> Buffer:
+def dump_range_binary(obj: Range[Any], dump: DumpFunc) -> Buffer:
     if not obj:
         return _EMPTY_HEAD
 
@@ -423,15 +423,21 @@ def dump_range_binary(obj: Range[Any], dump: Callable[[Any], Buffer]) -> Buffer:
 
     if obj.lower is not None:
         data = dump(obj.lower)
-        out += pack_len(len(data))
-        out += data
+        if data is not None:
+            out += pack_len(len(data))
+            out += data
+        else:
+            head |= RANGE_LB_INF
     else:
         head |= RANGE_LB_INF
 
     if obj.upper is not None:
         data = dump(obj.upper)
-        out += pack_len(len(data))
-        out += data
+        if data is not None:
+            out += pack_len(len(data))
+            out += data
+        else:
+            head |= RANGE_UB_INF
     else:
         head |= RANGE_UB_INF
 
@@ -461,9 +467,7 @@ class RangeLoader(BaseRangeLoader[T]):
         return load_range_text(data, self._load)[0]
 
 
-def load_range_text(
-    data: Buffer, load: Callable[[Buffer], Any]
-) -> Tuple[Range[Any], int]:
+def load_range_text(data: Buffer, load: LoadFunc) -> Tuple[Range[Any], int]:
     if data == b"empty":
         return Range(empty=True), 5
 
@@ -523,7 +527,7 @@ class RangeBinaryLoader(BaseRangeLoader[T]):
         return load_range_binary(data, self._load)
 
 
-def load_range_binary(data: Buffer, load: Callable[[Buffer], Any]) -> Range[Any]:
+def load_range_binary(data: Buffer, load: LoadFunc) -> Range[Any]:
     head = data[0]
     if head & RANGE_EMPTY:
         return Range(empty=True)