]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Dropped use of decorator to register builtin adapters
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 2 Jan 2021 02:47:06 +0000 (03:47 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 8 Jan 2021 01:32:29 +0000 (02:32 +0100)
Although the registration function is unwieldy already, it's good to get
more flexibility in when it should happen.

It also convinced me that flat is better than nested so the
psycopg3.types can be the facade for all the type-related objects.

More important, it should allow to override certain objects with C
equivalents.

17 files changed:
psycopg3/.flake8
psycopg3/psycopg3/__init__.py
psycopg3/psycopg3/adapt.py
psycopg3/psycopg3/dbapi20.py
psycopg3/psycopg3/types/__init__.py
psycopg3/psycopg3/types/array.py
psycopg3/psycopg3/types/composite.py
psycopg3/psycopg3/types/date.py
psycopg3/psycopg3/types/json.py
psycopg3/psycopg3/types/network.py
psycopg3/psycopg3/types/numeric.py
psycopg3/psycopg3/types/range.py
psycopg3/psycopg3/types/singletons.py
psycopg3/psycopg3/types/text.py
psycopg3/psycopg3/types/uuid.py
psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx
tox.ini

index 98bc11f7743f1599f6733be8b6f37b0d0ec3911d..ebb4945dd2a4aa86c11aa9f9d5637a6c11b493a5 100644 (file)
@@ -2,3 +2,4 @@
 [flake8]
 per-file-ignores =
     psycopg3/__init__.py: F401
+    psycopg3/types/__init__.py: F401
index 2aa334a77bb0bca34faef9b0ca40308c22cbf37d..be10c37db83ea962f8bb8f3d16870dc77534a3be 100644 (file)
@@ -5,7 +5,9 @@ psycopg3 -- PostgreSQL database adapter for Python
 # Copyright (C) 2020 The Psycopg Team
 
 from . import pq
+from . import types
 from .copy import Copy, AsyncCopy
+from .adapt import global_adapters
 from .cursor import AsyncCursor, Cursor
 from .errors import Warning, Error, InterfaceError, DatabaseError
 from .errors import DataError, OperationalError, IntegrityError
@@ -14,20 +16,21 @@ from ._column import Column
 from .connection import AsyncConnection, Connection, Notify
 from .transaction import Rollback, Transaction, AsyncTransaction
 
-from .dbapi20 import BINARY, DATETIME, NUMBER, ROWID, STRING
+from .dbapi20 import BINARY, DATETIME, NUMBER, ROWID, STRING, BinaryDumper
 from .dbapi20 import Binary, Date, DateFromTicks, Time, TimeFromTicks
 from .dbapi20 import Timestamp, TimestampFromTicks
 
 from .version import __version__
 
 # register default adapters
-from . import types
+types.register_default_globals(global_adapters)
 
 # DBAPI compliancy
 connect = Connection.connect
 apilevel = "2.0"
 threadsafety = 2
 paramstyle = "pyformat"
+BinaryDumper.register(Binary, global_adapters)  # dbapi20
 
 
 # Override adapters with fast version if available
index 888fcdfebece6bb60f8c59f4e4593109725c5ab0..5e6372f86689844ccef407c012e6417eb12724b9 100644 (file)
@@ -5,7 +5,7 @@ Entry point into the adaptation system.
 # Copyright (C) 2020 The Psycopg Team
 
 from abc import ABC, abstractmethod
-from typing import Any, Dict, Callable, List, Optional, Type, Union
+from typing import Any, Dict, List, Optional, Type, Union
 from typing import TYPE_CHECKING
 from . import pq
 from . import proto
@@ -72,21 +72,6 @@ class Dumper(ABC):
         adapters = context.adapters if context else global_adapters
         adapters.register_dumper(cls, this_cls)
 
-    @classmethod
-    def builtin(
-        cls, *types: Union[type, str]
-    ) -> Callable[[Type["Dumper"]], Type["Dumper"]]:
-        """
-        Decorator to mark a dumper class as default for a builtin type.
-        """
-
-        def builtin_(dumper: Type["Dumper"]) -> Type["Dumper"]:
-            for cls in types:
-                dumper.register(cls)
-            return dumper
-
-        return builtin_
-
 
 class Loader(ABC):
     """
@@ -107,33 +92,18 @@ class Loader(ABC):
 
     @classmethod
     def register(
-        cls, oid: int, context: Optional[AdaptContext] = None
+        cls, oid: Union[int, str], context: Optional[AdaptContext] = None
     ) -> None:
         """
         Configure *context* to use this loader to convert values with OID *oid*.
         """
+        if isinstance(oid, str):
+            oid = builtins[oid].oid
         adapters = context.adapters if context else global_adapters
         adapters.register_loader(oid, cls)
 
-    @classmethod
-    def builtin(
-        cls, *types: Union[int, str]
-    ) -> Callable[[Type["Loader"]], Type["Loader"]]:
-        """
-        Decorator to mark a loader class as default for a builtin type.
-        """
-
-        def builtin_(loader: Type["Loader"]) -> Type["Loader"]:
-            for cls in types:
-                if isinstance(cls, str):
-                    cls = builtins[cls].oid
-                loader.register(cls)
-            return loader
-
-        return builtin_
-
 
-class AdaptersMap:
+class AdaptersMap(AdaptContext):
     """
     Map oids to Loaders and types to Dumpers.
 
@@ -158,6 +128,15 @@ class AdaptersMap:
             self._loaders = [{}, {}]
             self._own_loaders = [True, True]
 
+    # implement the AdaptContext protocol too
+    @property
+    def adapters(self) -> "AdaptersMap":
+        return self
+
+    @property
+    def connection(self) -> Optional["BaseConnection"]:
+        return None
+
     def register_dumper(
         self, cls: Union[type, str], dumper: Type[Dumper]
     ) -> None:
@@ -205,8 +184,7 @@ class AdaptersMap:
             if scls in dumpers:
                 return dumpers[scls]
 
-        # If the adapter is not found, look for its name as a string
-        for scls in cls.__mro__:
+            # If the adapter is not found, look for its name as a string
             fqn = scls.__module__ + "." + scls.__qualname__
             if fqn in dumpers:
                 # Replace the class name with the class itself
index d414b719cd7f491f0f8876345c1dd83bbf3916c6..cc2a65820a3c433562abe960c6639043dce3763f 100644 (file)
@@ -50,7 +50,6 @@ class Binary:
         self.obj = obj
 
 
-@Dumper.builtin(Binary)
 class BinaryDumper(Dumper):
 
     format = Format.TEXT
index 357997ff36cedb6189179e042e5799724b57d867..e17a4178798eb8f1f7cddd36b91bbaa8d1dd9211 100644 (file)
@@ -4,15 +4,234 @@ psycopg3 types package
 
 # Copyright (C) 2020 The Psycopg Team
 
-
-from ..oids import builtins
+from ..oids import builtins, INVALID_OID
+from ..proto import AdaptContext
 
 # Register default adapters
-from . import array, composite, date, json, network, numeric  # noqa
-from . import range, singletons, text, uuid  # noqa
+from . import array, composite
+from . import range
+
+# Wrapper objects
+from .numeric import Int2, Int4, Int8, Oid
+from .json import Json, Jsonb
+from .range import Range, Int4Range, Int8Range, DecimalRange
+from .range import DateRange, DateTimeRange, DateTimeTZRange
+
+# Supper objects
+from .range import RangeInfo
+from .composite import CompositeInfo
+
+# Adapter objects
+from .text import (
+    StringDumper,
+    StringBinaryDumper,
+    TextLoader,
+    TextBinaryLoader,
+    BytesDumper,
+    BytesBinaryDumper,
+    ByteaLoader,
+    ByteaBinaryLoader,
+)
+from .numeric import (
+    IntDumper,
+    FloatDumper,
+    FloatBinaryDumper,
+    DecimalDumper,
+    Int2Dumper,
+    Int4Dumper,
+    Int8Dumper,
+    OidDumper,
+    Int2BinaryDumper,
+    Int4BinaryDumper,
+    Int8BinaryDumper,
+    OidBinaryDumper,
+    IntLoader,
+    Int2BinaryLoader,
+    Int4BinaryLoader,
+    Int8BinaryLoader,
+    OidBinaryLoader,
+    FloatLoader,
+    Float4BinaryLoader,
+    Float8BinaryLoader,
+    NumericLoader,
+)
+from .singletons import (
+    BoolDumper,
+    BoolBinaryDumper,
+    NoneDumper,
+    BoolLoader,
+    BoolBinaryLoader,
+)
+from .date import (
+    DateDumper,
+    TimeDumper,
+    DateTimeDumper,
+    TimeDeltaDumper,
+    DateLoader,
+    TimeLoader,
+    TimeTzLoader,
+    TimestampLoader,
+    TimestamptzLoader,
+    IntervalLoader,
+)
+from .json import (
+    JsonDumper,
+    JsonBinaryDumper,
+    JsonbDumper,
+    JsonbBinaryDumper,
+    JsonLoader,
+    JsonBinaryLoader,
+    JsonbBinaryLoader,
+)
+from .uuid import (
+    UUIDDumper,
+    UUIDBinaryDumper,
+    UUIDLoader,
+    UUIDBinaryLoader,
+)
+from .network import (
+    InterfaceDumper,
+    NetworkDumper,
+    InetLoader,
+    CidrLoader,
+)
+from .range import (
+    RangeDumper,
+    Int4RangeDumper,
+    Int8RangeDumper,
+    NumRangeDumper,
+    DateRangeDumper,
+    TimestampRangeDumper,
+    TimestampTZRangeDumper,
+    RangeLoader,
+    Int4RangeLoader,
+    Int8RangeLoader,
+    NumericRangeLoader,
+    DateRangeLoader,
+    TimestampRangeLoader,
+    TimestampTZRangeLoader,
+)
+from .array import (
+    ListDumper,
+    ListBinaryDumper,
+)
+from .composite import (
+    TupleDumper,
+    RecordLoader,
+    RecordBinaryLoader,
+    CompositeLoader,
+    CompositeBinaryLoader,
+)
+
+
+def register_default_globals(ctx: AdaptContext) -> None:
+    StringDumper.register(str, ctx)
+    StringBinaryDumper.register(str, ctx)
+    TextLoader.register(INVALID_OID, ctx)
+    TextLoader.register("bpchar", ctx)
+    TextLoader.register("name", ctx)
+    TextLoader.register("text", ctx)
+    TextLoader.register("varchar", ctx)
+    TextBinaryLoader.register("bpchar", ctx)
+    TextBinaryLoader.register("name", ctx)
+    TextBinaryLoader.register("text", ctx)
+    TextBinaryLoader.register("varchar", ctx)
+
+    BytesDumper.register(bytes, ctx)
+    BytesDumper.register(bytearray, ctx)
+    BytesDumper.register(memoryview, ctx)
+    BytesBinaryDumper.register(bytes, ctx)
+    BytesBinaryDumper.register(bytearray, ctx)
+    BytesBinaryDumper.register(memoryview, ctx)
+    ByteaLoader.register("bytea", ctx)
+    ByteaBinaryLoader.register(INVALID_OID, ctx)
+    ByteaBinaryLoader.register("bytea", ctx)
+
+    IntDumper.register(int, ctx)
+    FloatDumper.register(float, ctx)
+    Int8BinaryDumper.register(int, ctx)
+    FloatBinaryDumper.register(float, ctx)
+    DecimalDumper.register("decimal.Decimal", ctx)
+    Int2Dumper.register(Int2, ctx)
+    Int4Dumper.register(Int4, ctx)
+    Int8Dumper.register(Int8, ctx)
+    OidDumper.register(Oid, ctx)
+    Int2BinaryDumper.register(Int2, ctx)
+    Int4BinaryDumper.register(Int4, ctx)
+    Int8BinaryDumper.register(Int8, ctx)
+    OidBinaryDumper.register(Oid, ctx)
+    IntLoader.register("int2", ctx)
+    IntLoader.register("int4", ctx)
+    IntLoader.register("int8", ctx)
+    IntLoader.register("oid", ctx)
+    Int2BinaryLoader.register("int2", ctx)
+    Int4BinaryLoader.register("int4", ctx)
+    Int8BinaryLoader.register("int8", ctx)
+    OidBinaryLoader.register("oid", ctx)
+    FloatLoader.register("float4", ctx)
+    FloatLoader.register("float8", ctx)
+    Float4BinaryLoader.register("float4", ctx)
+    Float8BinaryLoader.register("float8", ctx)
+    NumericLoader.register("numeric", ctx)
+
+    BoolDumper.register(bool, ctx)
+    BoolBinaryDumper.register(bool, ctx)
+    NoneDumper.register(type(None), ctx)
+    BoolLoader.register("bool", ctx)
+    BoolBinaryLoader.register("bool", ctx)
+
+    DateDumper.register("datetime.date", ctx)
+    TimeDumper.register("datetime.time", ctx)
+    DateTimeDumper.register("datetime.datetime", ctx)
+    TimeDeltaDumper.register("datetime.timedelta", ctx)
+    DateLoader.register("date", ctx)
+    TimeLoader.register("time", ctx)
+    TimeTzLoader.register("timetz", ctx)
+    TimestampLoader.register("timestamp", ctx)
+    TimestamptzLoader.register("timestamptz", ctx)
+    IntervalLoader.register("interval", ctx)
+
+    JsonDumper.register(Json, ctx)
+    JsonBinaryDumper.register(Json, ctx)
+    JsonbDumper.register(Jsonb, ctx)
+    JsonbBinaryDumper.register(Jsonb, ctx)
+    JsonLoader.register("json", ctx)
+    JsonLoader.register("jsonb", ctx)
+    JsonBinaryLoader.register("json", ctx)
+    JsonbBinaryLoader.register("jsonb", ctx)
+
+    UUIDDumper.register("uuid.UUID", ctx)
+    UUIDBinaryDumper.register("uuid.UUID", ctx)
+    UUIDLoader.register("uuid", ctx)
+    UUIDBinaryLoader.register("uuid", ctx)
+
+    InterfaceDumper.register("ipaddress.IPv4Address", ctx)
+    InterfaceDumper.register("ipaddress.IPv6Address", ctx)
+    InterfaceDumper.register("ipaddress.IPv4Interface", ctx)
+    InterfaceDumper.register("ipaddress.IPv6Interface", ctx)
+    NetworkDumper.register("ipaddress.IPv4Network", ctx)
+    NetworkDumper.register("ipaddress.IPv6Network", ctx)
+    InetLoader.register("inet", ctx)
+    CidrLoader.register("cidr", ctx)
+
+    Int4RangeDumper.register(Int4Range, ctx)
+    Int8RangeDumper.register(Int8Range, ctx)
+    NumRangeDumper.register(DecimalRange, ctx)
+    DateRangeDumper.register(DateRange, ctx)
+    TimestampRangeDumper.register(DateTimeRange, ctx)
+    TimestampTZRangeDumper.register(DateTimeTZRange, ctx)
+    Int4RangeLoader.register("int4range", ctx)
+    Int8RangeLoader.register("int8range", ctx)
+    NumericRangeLoader.register("numrange", ctx)
+    DateRangeLoader.register("daterange", ctx)
+    TimestampRangeLoader.register("tsrange", ctx)
+    TimestampTZRangeLoader.register("tstzrange", ctx)
 
-# Register associations with array oids
-array.register_all_arrays()
+    ListDumper.register(list, ctx)
+    ListBinaryDumper.register(list, ctx)
 
+    TupleDumper.register(tuple, ctx)
+    RecordLoader.register("record", ctx)
+    RecordBinaryLoader.register("record", ctx)
 
-__all__ = ["builtins"]
+    array.register_all_arrays()
index c2dc45eaf0270395ebd7c6c97ad1720f8e2c2c21..d9b6fa616892eb121bbc2ec65646e0afcc511306 100644 (file)
@@ -39,7 +39,6 @@ class BaseListDumper(Dumper):
         return oid or TEXT_ARRAY_OID
 
 
-@Dumper.builtin(list)
 class ListDumper(BaseListDumper):
     # from https://www.postgresql.org/docs/current/arrays.html#ARRAYS-IO
     #
@@ -102,7 +101,6 @@ class ListDumper(BaseListDumper):
         return b"".join(tokens)
 
 
-@Dumper.builtin(list)
 class ListBinaryDumper(BaseListDumper):
 
     format = Format.BINARY
index 46439dc37d67414dc48d5ac2ddb4ff4ec06a5689..5ad3bee4ee1d61a2a1078cce9775cc747bf046cf 100644 (file)
@@ -182,7 +182,6 @@ class SequenceDumper(Dumper):
     _re_esc = re.compile(br"([\\\"])")
 
 
-@Dumper.builtin(tuple)
 class TupleDumper(SequenceDumper):
 
     # Should be this, but it doesn't work
@@ -231,7 +230,6 @@ class BaseCompositeLoader(Loader):
     _re_undouble = re.compile(br'(["\\])\1')
 
 
-@Loader.builtin("record")
 class RecordLoader(BaseCompositeLoader):
     def load(self, data: bytes) -> Tuple[Any, ...]:
         if data == b"()":
@@ -248,7 +246,6 @@ _struct_len = struct.Struct("!i")
 _struct_oidlen = struct.Struct("!Ii")
 
 
-@Loader.builtin("record")
 class RecordBinaryLoader(Loader):
 
     format = Format.BINARY
index 2555abd312b02a1a3463190ef35b0a2ca6387627..6d3499f949e4b1ebc2dee7ded900f9e73d2e609f 100644 (file)
@@ -15,7 +15,6 @@ from ..proto import AdaptContext
 from ..errors import InterfaceError, DataError
 
 
-@Dumper.builtin(date)
 class DateDumper(Dumper):
 
     format = Format.TEXT
@@ -27,7 +26,6 @@ class DateDumper(Dumper):
         return str(obj).encode("utf8")
 
 
-@Dumper.builtin(time)
 class TimeDumper(Dumper):
 
     format = Format.TEXT
@@ -37,7 +35,6 @@ class TimeDumper(Dumper):
         return str(obj).encode("utf8")
 
 
-@Dumper.builtin(datetime)
 class DateTimeDumper(Dumper):
 
     format = Format.TEXT
@@ -49,7 +46,6 @@ class DateTimeDumper(Dumper):
         return str(obj).encode("utf8")
 
 
-@Dumper.builtin(timedelta)
 class TimeDeltaDumper(Dumper):
 
     format = Format.TEXT
@@ -77,7 +73,6 @@ class TimeDeltaDumper(Dumper):
         )
 
 
-@Loader.builtin("date")
 class DateLoader(Loader):
 
     format = Format.TEXT
@@ -138,7 +133,6 @@ class DateLoader(Loader):
         return max(map(len, parts))
 
 
-@Loader.builtin("time")
 class TimeLoader(Loader):
 
     format = Format.TEXT
@@ -164,7 +158,6 @@ class TimeLoader(Loader):
         raise exc
 
 
-@Loader.builtin("timetz")
 class TimeTzLoader(TimeLoader):
 
     format = Format.TEXT
@@ -201,7 +194,6 @@ class TimeTzLoader(TimeLoader):
         return TimeTzLoader.load(self, data)
 
 
-@Loader.builtin("timestamp")
 class TimestampLoader(DateLoader):
 
     format = Format.TEXT
@@ -256,7 +248,6 @@ class TimestampLoader(DateLoader):
                 return 0
 
 
-@Loader.builtin("timestamptz")
 class TimestamptzLoader(TimestampLoader):
 
     format = Format.TEXT
@@ -320,7 +311,6 @@ class TimestamptzLoader(TimestampLoader):
         )
 
 
-@Loader.builtin("interval")
 class IntervalLoader(Loader):
 
     format = Format.TEXT
index 701c90fccff91b131ba7c31f8a46d4b2119aedc8..543a2674ed15528af9cba2b380bd8a7a2af085ce 100644 (file)
@@ -39,27 +39,23 @@ class _JsonDumper(Dumper):
         return obj.dumps().encode("utf-8")
 
 
-@Dumper.builtin(Json)
 class JsonDumper(_JsonDumper):
 
     format = Format.TEXT
     _oid = builtins["json"].oid
 
 
-@Dumper.builtin(Json)
 class JsonBinaryDumper(JsonDumper):
 
     format = Format.BINARY
 
 
-@Dumper.builtin(Jsonb)
 class JsonbDumper(_JsonDumper):
 
     format = Format.TEXT
     _oid = builtins["jsonb"].oid
 
 
-@Dumper.builtin(Jsonb)
 class JsonbBinaryDumper(JsonbDumper):
 
     format = Format.BINARY
@@ -68,7 +64,6 @@ class JsonbBinaryDumper(JsonbDumper):
         return b"\x01" + obj.dumps().encode("utf-8")
 
 
-@Loader.builtin("json", "jsonb")
 class JsonLoader(Loader):
 
     format = Format.TEXT
@@ -77,13 +72,11 @@ class JsonLoader(Loader):
         return json.loads(data)
 
 
-@Loader.builtin("json")
 class JsonBinaryLoader(JsonLoader):
 
     format = Format.BINARY
 
 
-@Loader.builtin("jsonb")
 class JsonbBinaryLoader(Loader):
 
     format = Format.BINARY
index 2494e9bdab8d2acaa1868821044c2ab89e169bad..6d8243531dbce3176459caa55ed97e558a61ed00 100644 (file)
@@ -24,12 +24,6 @@ ip_interface: Callable[[str], Interface]
 ip_network: Callable[[str], Network]
 
 
-@Dumper.builtin(
-    "ipaddress.IPv4Address",
-    "ipaddress.IPv6Address",
-    "ipaddress.IPv4Interface",
-    "ipaddress.IPv6Interface",
-)
 class InterfaceDumper(Dumper):
 
     format = Format.TEXT
@@ -39,7 +33,6 @@ class InterfaceDumper(Dumper):
         return str(obj).encode("utf8")
 
 
-@Dumper.builtin("ipaddress.IPv4Network", "ipaddress.IPv6Network")
 class NetworkDumper(Dumper):
 
     format = Format.TEXT
@@ -59,7 +52,6 @@ class _LazyIpaddress(Loader):
             imported = True
 
 
-@Loader.builtin("inet")
 class InetLoader(_LazyIpaddress):
 
     format = Format.TEXT
@@ -71,7 +63,6 @@ class InetLoader(_LazyIpaddress):
             return ip_address(data.decode("utf8"))
 
 
-@Loader.builtin("cidr")
 class CidrLoader(_LazyIpaddress):
 
     format = Format.TEXT
index 54723d80dc04b0ae586b9e0ea01abf41f58e3b06..f71d9216c20205c91711ad8ba7bb125946b71ce3 100644 (file)
@@ -77,12 +77,10 @@ class SpecialValuesDumper(NumberDumper):
         return value if obj >= 0 else b" " + value
 
 
-@Dumper.builtin(int)
 class IntDumper(NumberDumper):
     _oid = builtins["int8"].oid
 
 
-@Dumper.builtin(float)
 class FloatDumper(SpecialValuesDumper):
 
     format = Format.TEXT
@@ -95,7 +93,6 @@ class FloatDumper(SpecialValuesDumper):
     }
 
 
-@Dumper.builtin(float)
 class FloatBinaryDumper(Dumper):
 
     format = Format.BINARY
@@ -105,7 +102,6 @@ class FloatBinaryDumper(Dumper):
         return _pack_float8(obj)
 
 
-@Dumper.builtin(Decimal)
 class DecimalDumper(SpecialValuesDumper):
 
     _oid = builtins["numeric"].oid
@@ -117,27 +113,22 @@ class DecimalDumper(SpecialValuesDumper):
     }
 
 
-@Dumper.builtin(Int2)
 class Int2Dumper(NumberDumper):
     _oid = builtins["int2"].oid
 
 
-@Dumper.builtin(Int4)
 class Int4Dumper(NumberDumper):
     _oid = builtins["int4"].oid
 
 
-@Dumper.builtin(Int8)
 class Int8Dumper(NumberDumper):
     _oid = builtins["int8"].oid
 
 
-@Dumper.builtin(Oid)
 class OidDumper(NumberDumper):
     _oid = builtins["oid"].oid
 
 
-@Dumper.builtin(Int2)
 class Int2BinaryDumper(Int2Dumper):
 
     format = Format.BINARY
@@ -146,7 +137,6 @@ class Int2BinaryDumper(Int2Dumper):
         return _pack_int2(obj)
 
 
-@Dumper.builtin(Int4)
 class Int4BinaryDumper(Int4Dumper):
 
     format = Format.BINARY
@@ -155,7 +145,6 @@ class Int4BinaryDumper(Int4Dumper):
         return _pack_int4(obj)
 
 
-@Dumper.builtin(int, Int8)
 class Int8BinaryDumper(Int8Dumper):
 
     format = Format.BINARY
@@ -164,7 +153,6 @@ class Int8BinaryDumper(Int8Dumper):
         return _pack_int8(obj)
 
 
-@Dumper.builtin(Oid)
 class OidBinaryDumper(OidDumper):
 
     format = Format.BINARY
@@ -173,7 +161,6 @@ class OidBinaryDumper(OidDumper):
         return _pack_uint4(obj)
 
 
-@Loader.builtin("int2", "int4", "int8", "oid")
 class IntLoader(Loader):
 
     format = Format.TEXT
@@ -183,7 +170,6 @@ class IntLoader(Loader):
         return int(data)
 
 
-@Loader.builtin("int2")
 class Int2BinaryLoader(Loader):
 
     format = Format.BINARY
@@ -192,7 +178,6 @@ class Int2BinaryLoader(Loader):
         return _unpack_int2(data)[0]
 
 
-@Loader.builtin("int4")
 class Int4BinaryLoader(Loader):
 
     format = Format.BINARY
@@ -201,7 +186,6 @@ class Int4BinaryLoader(Loader):
         return _unpack_int4(data)[0]
 
 
-@Loader.builtin("int8")
 class Int8BinaryLoader(Loader):
 
     format = Format.BINARY
@@ -210,7 +194,6 @@ class Int8BinaryLoader(Loader):
         return _unpack_int8(data)[0]
 
 
-@Loader.builtin("oid")
 class OidBinaryLoader(Loader):
 
     format = Format.BINARY
@@ -219,7 +202,6 @@ class OidBinaryLoader(Loader):
         return _unpack_uint4(data)[0]
 
 
-@Loader.builtin("float4", "float8")
 class FloatLoader(Loader):
 
     format = Format.TEXT
@@ -229,7 +211,6 @@ class FloatLoader(Loader):
         return float(data)
 
 
-@Loader.builtin("float4")
 class Float4BinaryLoader(Loader):
 
     format = Format.BINARY
@@ -238,7 +219,6 @@ class Float4BinaryLoader(Loader):
         return _unpack_float4(data)[0]
 
 
-@Loader.builtin("float8")
 class Float8BinaryLoader(Loader):
 
     format = Format.BINARY
@@ -247,7 +227,6 @@ class Float8BinaryLoader(Loader):
         return _unpack_float8(data)[0]
 
 
-@Loader.builtin("numeric")
 class NumericLoader(Loader):
 
     format = Format.TEXT
index ce5086af2430679a3f35bd457d2aff78d11136a5..d204d44e6220ddddeee2f7150c60225c22e711d1 100644 (file)
@@ -287,32 +287,26 @@ class DateTimeTZRange(Range[datetime]):
 # Dumpers for builtin range types
 
 
-@Dumper.builtin(Int4Range)
 class Int4RangeDumper(RangeDumper):
     _oid = builtins["int4range"].oid
 
 
-@Dumper.builtin(Int8Range)
 class Int8RangeDumper(RangeDumper):
     _oid = builtins["int8range"].oid
 
 
-@Dumper.builtin(DecimalRange)
 class NumRangeDumper(RangeDumper):
     _oid = builtins["numrange"].oid
 
 
-@Dumper.builtin(DateRange)
 class DateRangeDumper(RangeDumper):
     _oid = builtins["daterange"].oid
 
 
-@Dumper.builtin(DateTimeRange)
 class TimestampRangeDumper(RangeDumper):
     _oid = builtins["tsrange"].oid
 
 
-@Dumper.builtin(DateTimeTZRange)
 class TimestampTZRangeDumper(RangeDumper):
     _oid = builtins["tstzrange"].oid
 
@@ -320,37 +314,31 @@ class TimestampTZRangeDumper(RangeDumper):
 # Loaders for builtin range types
 
 
-@Loader.builtin("int4range")
 class Int4RangeLoader(RangeLoader[int]):
     subtype_oid = builtins["int4"].oid
     cls = Int4Range
 
 
-@Loader.builtin("int8range")
 class Int8RangeLoader(RangeLoader[int]):
     subtype_oid = builtins["int8"].oid
     cls = Int8Range
 
 
-@Loader.builtin("numrange")
 class NumericRangeLoader(RangeLoader[Decimal]):
     subtype_oid = builtins["numeric"].oid
     cls = DecimalRange
 
 
-@Loader.builtin("daterange")
 class DateRangeLoader(RangeLoader[date]):
     subtype_oid = builtins["date"].oid
     cls = DateRange
 
 
-@Loader.builtin("tsrange")
 class TimestampRangeLoader(RangeLoader[datetime]):
     subtype_oid = builtins["timestamp"].oid
     cls = DateTimeRange
 
 
-@Loader.builtin("tstzrange")
 class TimestampTZRangeLoader(RangeLoader[datetime]):
     subtype_oid = builtins["timestamptz"].oid
     cls = DateTimeTZRange
index a880184166907da516b08917f4cab32d31b090a5..8f1b87be7a4f435f4f7d93b7f92b0a1560d83bbc 100644 (file)
@@ -8,7 +8,6 @@ from ..oids import builtins
 from ..adapt import Dumper, Loader, Format
 
 
-@Dumper.builtin(bool)
 class BoolDumper(Dumper):
 
     format = Format.TEXT
@@ -21,7 +20,6 @@ class BoolDumper(Dumper):
         return b"true" if obj else b"false"
 
 
-@Dumper.builtin(bool)
 class BoolBinaryDumper(Dumper):
 
     format = Format.BINARY
@@ -31,7 +29,6 @@ class BoolBinaryDumper(Dumper):
         return b"\x01" if obj else b"\x00"
 
 
-@Dumper.builtin(type(None))
 class NoneDumper(Dumper):
     """
     Not a complete dumper as it doesn't implement dump(), but it implements
@@ -47,7 +44,6 @@ class NoneDumper(Dumper):
         return b"NULL"
 
 
-@Loader.builtin("bool")
 class BoolLoader(Loader):
 
     format = Format.TEXT
@@ -56,7 +52,6 @@ class BoolLoader(Loader):
         return data == b"t"
 
 
-@Loader.builtin("bool")
 class BoolBinaryLoader(Loader):
 
     format = Format.BINARY
index a4306cddf36f0831460201689a0494b3b2b1277b..d671bc47492631ace288965e4406a548066e820b 100644 (file)
@@ -7,7 +7,7 @@ Adapters for textual types.
 from typing import Optional, Union, TYPE_CHECKING
 
 from ..pq import Escaping
-from ..oids import builtins, INVALID_OID
+from ..oids import builtins
 from ..adapt import Dumper, Loader, Format
 from ..proto import AdaptContext
 from ..errors import DataError
@@ -30,7 +30,6 @@ class _StringDumper(Dumper):
                 self._encoding = enc
 
 
-@Dumper.builtin(str)
 class StringBinaryDumper(_StringDumper):
 
     format = Format.BINARY
@@ -40,7 +39,6 @@ class StringBinaryDumper(_StringDumper):
         return obj.encode(self._encoding)
 
 
-@Dumper.builtin(str)
 class StringDumper(_StringDumper):
 
     format = Format.TEXT
@@ -54,7 +52,6 @@ class StringDumper(_StringDumper):
             return obj.encode(self._encoding)
 
 
-@Loader.builtin(INVALID_OID, "bpchar", "name", "text", "varchar")
 class TextLoader(Loader):
 
     format = Format.TEXT
@@ -75,13 +72,11 @@ class TextLoader(Loader):
             return data
 
 
-@Loader.builtin("bpchar", "name", "text", "varchar")
 class TextBinaryLoader(TextLoader):
 
     format = Format.BINARY
 
 
-@Dumper.builtin(bytes, bytearray, memoryview)
 class BytesDumper(Dumper):
 
     format = Format.TEXT
@@ -99,7 +94,6 @@ class BytesDumper(Dumper):
         return self._esc.escape_bytea(obj)
 
 
-@Dumper.builtin(bytes, bytearray, memoryview)
 class BytesBinaryDumper(Dumper):
 
     format = Format.BINARY
@@ -112,7 +106,6 @@ class BytesBinaryDumper(Dumper):
         return obj
 
 
-@Loader.builtin("bytea")
 class ByteaLoader(Loader):
 
     format = Format.TEXT
@@ -127,7 +120,6 @@ class ByteaLoader(Loader):
         return self._escaping.unescape_bytea(data)
 
 
-@Loader.builtin("bytea", INVALID_OID)
 class ByteaBinaryLoader(Loader):
 
     format = Format.BINARY
index bcf8f94d9456ae22ca219ce31d76dad9c97b3ccf..ec2817d8ecc5afb80b58ea6858bb7a4e9c3ff5ea 100644 (file)
@@ -18,7 +18,6 @@ imported = False
 UUID: Callable[..., "uuid.UUID"]
 
 
-@Dumper.builtin("uuid.UUID")
 class UUIDDumper(Dumper):
 
     format = Format.TEXT
@@ -28,7 +27,6 @@ class UUIDDumper(Dumper):
         return obj.hex.encode("utf8")
 
 
-@Dumper.builtin("uuid.UUID")
 class UUIDBinaryDumper(UUIDDumper):
 
     format = Format.BINARY
@@ -37,7 +35,6 @@ class UUIDBinaryDumper(UUIDDumper):
         return obj.bytes
 
 
-@Loader.builtin("uuid")
 class UUIDLoader(Loader):
 
     format = Format.TEXT
@@ -54,7 +51,6 @@ class UUIDLoader(Loader):
         return UUID(data.decode("utf8"))
 
 
-@Loader.builtin("uuid")
 class UUIDBinaryLoader(UUIDLoader):
 
     format = Format.BINARY
index e8d48bd90a9f855b765adf96a4e86e9e6e03f936..20391a355d280b0473eef79ff1e73109c7446d09 100644 (file)
@@ -160,10 +160,14 @@ cdef class CLoader:
     @classmethod
     def register(
         cls,
-        int oid,
+        oid: Union[int, str],
         context: Optional["AdaptContext"] = None,
         int format = Format.TEXT,
     ) -> None:
+        if isinstance(oid, str):
+            from psycopg3.oids import builtins
+            oid = builtins[oid].oid
+
         if context is not None:
             adapters = context.adapters
         else:
diff --git a/tox.ini b/tox.ini
index 34b21b6ac987df30c45eb3177f7a69921e97dd6d..a44bff9a4e442574dd8eea4033cc8853000926c6 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -24,3 +24,4 @@ ignore = W503, E203
 extend-exclude = .venv
 per-file-ignores =
     ./psycopg3/psycopg3/__init__.py: F401
+    ./psycopg3/psycopg3/types/__init__.py: F401