From: Daniele Varrazzo Date: Sat, 2 Jan 2021 02:47:06 +0000 (+0100) Subject: Dropped use of decorator to register builtin adapters X-Git-Tag: 3.0.dev0~206 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=282c1841419b36519ec6b2d79f1ddc2e4b820d53;p=thirdparty%2Fpsycopg.git Dropped use of decorator to register builtin adapters 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. --- diff --git a/psycopg3/.flake8 b/psycopg3/.flake8 index 98bc11f77..ebb4945dd 100644 --- a/psycopg3/.flake8 +++ b/psycopg3/.flake8 @@ -2,3 +2,4 @@ [flake8] per-file-ignores = psycopg3/__init__.py: F401 + psycopg3/types/__init__.py: F401 diff --git a/psycopg3/psycopg3/__init__.py b/psycopg3/psycopg3/__init__.py index 2aa334a77..be10c37db 100644 --- a/psycopg3/psycopg3/__init__.py +++ b/psycopg3/psycopg3/__init__.py @@ -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 diff --git a/psycopg3/psycopg3/adapt.py b/psycopg3/psycopg3/adapt.py index 888fcdfeb..5e6372f86 100644 --- a/psycopg3/psycopg3/adapt.py +++ b/psycopg3/psycopg3/adapt.py @@ -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 diff --git a/psycopg3/psycopg3/dbapi20.py b/psycopg3/psycopg3/dbapi20.py index d414b719c..cc2a65820 100644 --- a/psycopg3/psycopg3/dbapi20.py +++ b/psycopg3/psycopg3/dbapi20.py @@ -50,7 +50,6 @@ class Binary: self.obj = obj -@Dumper.builtin(Binary) class BinaryDumper(Dumper): format = Format.TEXT diff --git a/psycopg3/psycopg3/types/__init__.py b/psycopg3/psycopg3/types/__init__.py index 357997ff3..e17a41787 100644 --- a/psycopg3/psycopg3/types/__init__.py +++ b/psycopg3/psycopg3/types/__init__.py @@ -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() diff --git a/psycopg3/psycopg3/types/array.py b/psycopg3/psycopg3/types/array.py index c2dc45eaf..d9b6fa616 100644 --- a/psycopg3/psycopg3/types/array.py +++ b/psycopg3/psycopg3/types/array.py @@ -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 diff --git a/psycopg3/psycopg3/types/composite.py b/psycopg3/psycopg3/types/composite.py index 46439dc37..5ad3bee4e 100644 --- a/psycopg3/psycopg3/types/composite.py +++ b/psycopg3/psycopg3/types/composite.py @@ -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 diff --git a/psycopg3/psycopg3/types/date.py b/psycopg3/psycopg3/types/date.py index 2555abd31..6d3499f94 100644 --- a/psycopg3/psycopg3/types/date.py +++ b/psycopg3/psycopg3/types/date.py @@ -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 diff --git a/psycopg3/psycopg3/types/json.py b/psycopg3/psycopg3/types/json.py index 701c90fcc..543a2674e 100644 --- a/psycopg3/psycopg3/types/json.py +++ b/psycopg3/psycopg3/types/json.py @@ -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 diff --git a/psycopg3/psycopg3/types/network.py b/psycopg3/psycopg3/types/network.py index 2494e9bda..6d8243531 100644 --- a/psycopg3/psycopg3/types/network.py +++ b/psycopg3/psycopg3/types/network.py @@ -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 diff --git a/psycopg3/psycopg3/types/numeric.py b/psycopg3/psycopg3/types/numeric.py index 54723d80d..f71d9216c 100644 --- a/psycopg3/psycopg3/types/numeric.py +++ b/psycopg3/psycopg3/types/numeric.py @@ -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 diff --git a/psycopg3/psycopg3/types/range.py b/psycopg3/psycopg3/types/range.py index ce5086af2..d204d44e6 100644 --- a/psycopg3/psycopg3/types/range.py +++ b/psycopg3/psycopg3/types/range.py @@ -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 diff --git a/psycopg3/psycopg3/types/singletons.py b/psycopg3/psycopg3/types/singletons.py index a88018416..8f1b87be7 100644 --- a/psycopg3/psycopg3/types/singletons.py +++ b/psycopg3/psycopg3/types/singletons.py @@ -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 diff --git a/psycopg3/psycopg3/types/text.py b/psycopg3/psycopg3/types/text.py index a4306cddf..d671bc474 100644 --- a/psycopg3/psycopg3/types/text.py +++ b/psycopg3/psycopg3/types/text.py @@ -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 diff --git a/psycopg3/psycopg3/types/uuid.py b/psycopg3/psycopg3/types/uuid.py index bcf8f94d9..ec2817d8e 100644 --- a/psycopg3/psycopg3/types/uuid.py +++ b/psycopg3/psycopg3/types/uuid.py @@ -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 diff --git a/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx b/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx index e8d48bd90..20391a355 100644 --- a/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx +++ b/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx @@ -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 34b21b6ac..a44bff9a4 100644 --- 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