From: Daniele Varrazzo Date: Fri, 3 Apr 2020 00:27:59 +0000 (+1300) Subject: Added object to map oid and data types X-Git-Tag: 3.0.dev0~621 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6795d025a17ecc8ea6856fc976ecd4d73424ec21;p=thirdparty%2Fpsycopg.git Added object to map oid and data types --- diff --git a/psycopg3/adapt.py b/psycopg3/adapt.py index b25b4894e..fec5e3dc9 100644 --- a/psycopg3/adapt.py +++ b/psycopg3/adapt.py @@ -12,23 +12,25 @@ from typing import Tuple, Union from . import errors as e from .pq import Format, PGresult from .cursor import BaseCursor -from .types.oids import type_oid, INVALID_OID +from .types.oids import builtins, INVALID_OID from .connection import BaseConnection -from .utils.typing import DecodeFunc, Oid +from .utils.typing import DecodeFunc + +TEXT_OID = builtins["text"].oid # Type system AdaptContext = Union[None, BaseConnection, BaseCursor] -MaybeOid = Union[Optional[bytes], Tuple[Optional[bytes], Oid]] +MaybeOid = Union[Optional[bytes], Tuple[Optional[bytes], int]] AdapterFunc = Callable[[Any], MaybeOid] AdapterType = Union["Adapter", AdapterFunc] AdaptersMap = Dict[Tuple[type, Format], AdapterType] TypecasterFunc = Callable[[bytes], Any] TypecasterType = Union["Typecaster", TypecasterFunc] -TypecastersMap = Dict[Tuple[Oid, Format], TypecasterType] +TypecastersMap = Dict[Tuple[int, Format], TypecasterType] class Adapter: @@ -38,7 +40,7 @@ class Adapter: self.cls = cls self.conn = conn - def adapt(self, obj: Any) -> Union[bytes, Tuple[bytes, Oid]]: + def adapt(self, obj: Any) -> Union[bytes, Tuple[bytes, int]]: raise NotImplementedError() @staticmethod @@ -100,7 +102,7 @@ class Adapter: class Typecaster: globals: TypecastersMap = {} - def __init__(self, oid: Oid, conn: Optional[BaseConnection]): + def __init__(self, oid: int, conn: Optional[BaseConnection]): self.oid = oid self.conn = conn @@ -109,7 +111,7 @@ class Typecaster: @staticmethod def register( - oid: Oid, + oid: int, caster: TypecasterType, context: AdaptContext = None, format: Format = Format.TEXT, @@ -142,12 +144,12 @@ class Typecaster: @staticmethod def register_binary( - oid: Oid, caster: TypecasterType, context: AdaptContext = None, + oid: int, caster: TypecasterType, context: AdaptContext = None, ) -> TypecasterType: return Typecaster.register(oid, caster, context, format=Format.BINARY) @staticmethod - def text(oid: Oid) -> Callable[[Any], Any]: + def text(oid: int) -> Callable[[Any], Any]: def register_caster_(caster: TypecasterType) -> TypecasterType: Typecaster.register(oid, caster) return caster @@ -155,7 +157,7 @@ class Typecaster: return register_caster_ @staticmethod - def binary(oid: Oid) -> Callable[[Any], Any]: + def binary(oid: int) -> Callable[[Any], Any]: def register_binary_caster_(caster: TypecasterType) -> TypecasterType: Typecaster.register_binary(oid, caster) return caster @@ -222,7 +224,7 @@ class Transformer: def adapt_sequence( self, objs: Sequence[Any], fmts: Sequence[Format] - ) -> Tuple[List[Optional[bytes]], List[Oid]]: + ) -> Tuple[List[Optional[bytes]], List[int]]: out = [] types = [] @@ -232,7 +234,7 @@ class Transformer: oid = data[1] data = data[0] else: - oid = type_oid["text"] + oid = TEXT_OID out.append(data) types.append(oid) @@ -241,7 +243,7 @@ class Transformer: def adapt(self, obj: None, fmt: Format = Format.TEXT) -> MaybeOid: if obj is None: - return None, type_oid["text"] + return None, TEXT_OID cls = type(obj) func = self.get_adapt_function(cls, fmt) @@ -287,7 +289,7 @@ class Transformer: yield v def cast( - self, data: Optional[bytes], oid: Oid, fmt: Format = Format.TEXT + self, data: Optional[bytes], oid: int, fmt: Format = Format.TEXT ) -> Any: if data is not None: f = self.get_cast_function(oid, fmt) @@ -295,7 +297,7 @@ class Transformer: else: return None - def get_cast_function(self, oid: Oid, fmt: Format) -> TypecasterFunc: + def get_cast_function(self, oid: int, fmt: Format) -> TypecasterFunc: try: return self._cast_funcs[oid, fmt] except KeyError: @@ -307,7 +309,7 @@ class Transformer: else: return cast(TypecasterFunc, caster) - def lookup_caster(self, oid: Oid, fmt: Format) -> TypecasterType: + def lookup_caster(self, oid: int, fmt: Format) -> TypecasterType: key = (oid, fmt) cur = self.cursor @@ -330,7 +332,7 @@ class UnknownCaster(Typecaster): Fallback object to convert unknown types to Python """ - def __init__(self, oid: Oid, conn: Optional[BaseConnection]): + def __init__(self, oid: int, conn: Optional[BaseConnection]): super().__init__(oid, conn) self.decode: DecodeFunc if conn is not None: diff --git a/psycopg3/pq/pq_ctypes.py b/psycopg3/pq/pq_ctypes.py index 66030151b..626275ed4 100644 --- a/psycopg3/pq/pq_ctypes.py +++ b/psycopg3/pq/pq_ctypes.py @@ -25,7 +25,6 @@ from .enums import ( from .misc import error_message, ConninfoOption from . import _pq_ctypes as impl from ..errors import OperationalError -from ..utils.typing import Oid def version() -> int: @@ -198,7 +197,7 @@ class PGconn: self, command: bytes, param_values: Sequence[Optional[bytes]], - param_types: Optional[Sequence[Oid]] = None, + param_types: Optional[Sequence[int]] = None, param_formats: Optional[Sequence[Format]] = None, result_format: Format = Format.TEXT, ) -> "PGresult": @@ -214,7 +213,7 @@ class PGconn: self, command: bytes, param_values: Sequence[Optional[bytes]], - param_types: Optional[Sequence[Oid]] = None, + param_types: Optional[Sequence[int]] = None, param_formats: Optional[Sequence[Format]] = None, result_format: Format = Format.TEXT, ) -> None: @@ -230,7 +229,7 @@ class PGconn: self, command: bytes, param_values: Sequence[Optional[bytes]], - param_types: Optional[Sequence[Oid]] = None, + param_types: Optional[Sequence[int]] = None, param_formats: Optional[Sequence[Format]] = None, result_format: Format = Format.TEXT, ) -> Any: @@ -282,7 +281,7 @@ class PGconn: self, name: bytes, command: bytes, - param_types: Optional[Sequence[Oid]] = None, + param_types: Optional[Sequence[int]] = None, ) -> "PGresult": if not isinstance(name, bytes): raise TypeError(f"'name' must be bytes, got {type(name)} instead") @@ -432,8 +431,8 @@ class PGresult: def fname(self, column_number: int) -> bytes: return impl.PQfname(self.pgresult_ptr, column_number) - def ftable(self, column_number: int) -> Oid: - return Oid(impl.PQftable(self.pgresult_ptr, column_number)) + def ftable(self, column_number: int) -> int: + return impl.PQftable(self.pgresult_ptr, column_number) def ftablecol(self, column_number: int) -> int: return impl.PQftablecol(self.pgresult_ptr, column_number) @@ -441,8 +440,8 @@ class PGresult: def fformat(self, column_number: int) -> Format: return Format(impl.PQfformat(self.pgresult_ptr, column_number)) - def ftype(self, column_number: int) -> Oid: - return Oid(impl.PQftype(self.pgresult_ptr, column_number)) + def ftype(self, column_number: int) -> int: + return impl.PQftype(self.pgresult_ptr, column_number) def fmod(self, column_number: int) -> int: return impl.PQfmod(self.pgresult_ptr, column_number) @@ -473,8 +472,8 @@ class PGresult: def nparams(self) -> int: return impl.PQnparams(self.pgresult_ptr) - def param_type(self, param_number: int) -> Oid: - return Oid(impl.PQparamtype(self.pgresult_ptr, param_number)) + def param_type(self, param_number: int) -> int: + return impl.PQparamtype(self.pgresult_ptr, param_number) @property def command_status(self) -> bytes: @@ -486,8 +485,8 @@ class PGresult: return int(rv) if rv else None @property - def oid_value(self) -> Oid: - return Oid(impl.PQoidValue(self.pgresult_ptr)) + def oid_value(self) -> int: + return impl.PQoidValue(self.pgresult_ptr) class Conninfo: diff --git a/psycopg3/types/__init__.py b/psycopg3/types/__init__.py index c988c0fdb..5dbaf1073 100644 --- a/psycopg3/types/__init__.py +++ b/psycopg3/types/__init__.py @@ -5,9 +5,9 @@ psycopg3 types package # Copyright (C) 2020 The Psycopg Team -from .oids import type_oid +from .oids import builtins # Register default adapters from . import numeric, text # noqa -__all__ = ["type_oid"] +__all__ = ["builtins"] diff --git a/psycopg3/types/numeric.py b/psycopg3/types/numeric.py index efb6b46a1..9b22a2bb6 100644 --- a/psycopg3/types/numeric.py +++ b/psycopg3/types/numeric.py @@ -10,8 +10,10 @@ from decimal import Decimal from typing import Tuple from ..adapt import Adapter, Typecaster -from ..utils.typing import Oid -from .oids import type_oid +from .oids import builtins + +FLOAT8_OID = builtins["float8"].oid +NUMERIC_OID = builtins["numeric"].oid _encode = codecs.lookup("ascii").encode _decode = codecs.lookup("ascii").decode @@ -25,86 +27,86 @@ _float8_struct = struct.Struct("!d") @Adapter.text(int) -def adapt_int(obj: int) -> Tuple[bytes, Oid]: +def adapt_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], type_oid["numeric"] + return _encode(str(obj))[0], NUMERIC_OID @Adapter.text(float) -def adapt_float(obj: float) -> Tuple[bytes, Oid]: +def adapt_float(obj: float) -> Tuple[bytes, int]: # Float can't be bigger than this instead - return _encode(str(obj))[0], type_oid["float8"] + return _encode(str(obj))[0], FLOAT8_OID @Adapter.text(Decimal) -def adapt_decimal(obj: Decimal) -> Tuple[bytes, Oid]: +def adapt_decimal(obj: Decimal) -> Tuple[bytes, int]: # Float can't be bigger than this instead - return _encode(str(obj))[0], type_oid["numeric"] + return _encode(str(obj))[0], NUMERIC_OID _bool_adapt = { - True: (b"t", type_oid["bool"]), - False: (b"f", type_oid["bool"]), + True: (b"t", builtins["bool"].oid), + False: (b"f", builtins["bool"].oid), } @Adapter.text(bool) -def adapt_bool(obj: bool) -> Tuple[bytes, Oid]: +def adapt_bool(obj: bool) -> Tuple[bytes, int]: return _bool_adapt[obj] -@Typecaster.text(type_oid["int2"]) -@Typecaster.text(type_oid["int4"]) -@Typecaster.text(type_oid["int8"]) -@Typecaster.text(type_oid["oid"]) +@Typecaster.text(builtins["int2"].oid) +@Typecaster.text(builtins["int4"].oid) +@Typecaster.text(builtins["int8"].oid) +@Typecaster.text(builtins["oid"].oid) def cast_int(data: bytes) -> int: return int(_decode(data)[0]) -@Typecaster.binary(type_oid["int2"]) +@Typecaster.binary(builtins["int2"].oid) def cast_binary_int2(data: bytes) -> int: rv: int = _int2_struct.unpack(data)[0] return rv -@Typecaster.binary(type_oid["int4"]) +@Typecaster.binary(builtins["int4"].oid) def cast_binary_int4(data: bytes) -> int: rv: int = _int4_struct.unpack(data)[0] return rv -@Typecaster.binary(type_oid["int8"]) +@Typecaster.binary(builtins["int8"].oid) def cast_binary_int8(data: bytes) -> int: rv: int = _int8_struct.unpack(data)[0] return rv -@Typecaster.binary(type_oid["oid"]) +@Typecaster.binary(builtins["oid"].oid) def cast_binary_oid(data: bytes) -> int: rv: int = _oid_struct.unpack(data)[0] return rv -@Typecaster.text(type_oid["float4"]) -@Typecaster.text(type_oid["float8"]) +@Typecaster.text(builtins["float4"].oid) +@Typecaster.text(builtins["float8"].oid) def cast_float(data: bytes) -> float: # it supports bytes directly return float(data) -@Typecaster.binary(type_oid["float4"]) +@Typecaster.binary(builtins["float4"].oid) def cast_binary_float4(data: bytes) -> float: rv: float = _float4_struct.unpack(data)[0] return rv -@Typecaster.binary(type_oid["float8"]) +@Typecaster.binary(builtins["float8"].oid) def cast_binary_float8(data: bytes) -> float: rv: float = _float8_struct.unpack(data)[0] return rv -@Typecaster.text(type_oid["numeric"]) +@Typecaster.text(builtins["numeric"].oid) def cast_numeric(data: bytes) -> Decimal: return Decimal(_decode(data)[0]) @@ -113,11 +115,11 @@ _bool_casts = {b"t": True, b"f": False} _bool_binary_casts = {b"\x01": True, b"\x00": False} -@Typecaster.text(type_oid["bool"]) +@Typecaster.text(builtins["bool"].oid) def cast_bool(data: bytes) -> bool: return _bool_casts[data] -@Typecaster.binary(type_oid["bool"]) +@Typecaster.binary(builtins["bool"].oid) def cast_binary_bool(data: bytes) -> bool: return _bool_binary_casts[data] diff --git a/psycopg3/types/oids.py b/psycopg3/types/oids.py index 2ec524bfc..95bdb2a5b 100644 --- a/psycopg3/types/oids.py +++ b/psycopg3/types/oids.py @@ -8,11 +8,9 @@ to a Postgres server. # Copyright (C) 2020 The Psycopg Team import re -from typing import Dict, NamedTuple +from typing import Dict, Optional, NamedTuple, Union -from psycopg3.utils.typing import Oid - -INVALID_OID = Oid(0) +INVALID_OID = 0 class TypeInfo(NamedTuple): @@ -23,95 +21,122 @@ class TypeInfo(NamedTuple): delimiter: str -_oids_table = [ - TypeInfo(*r) - for r in [ - # fmt: off - # autogenerated: start - - # Generated from PostgreSQL 12.2 - - ('aclitem', 1033, 1034, 'aclitem', ','), - ('any', 2276, 0, '"any"', ','), - ('anyarray', 2277, 0, 'anyarray', ','), - ('anyelement', 2283, 0, 'anyelement', ','), - ('anyenum', 3500, 0, 'anyenum', ','), - ('anynonarray', 2776, 0, 'anynonarray', ','), - ('anyrange', 3831, 0, 'anyrange', ','), - ('bit', 1560, 1561, 'bit', ','), - ('bool', 16, 1000, 'boolean', ','), - ('box', 603, 1020, 'box', ';'), - ('bpchar', 1042, 1014, 'character', ','), - ('bytea', 17, 1001, 'bytea', ','), - ('char', 18, 1002, '"char"', ','), - ('cid', 29, 1012, 'cid', ','), - ('cidr', 650, 651, 'cidr', ','), - ('circle', 718, 719, 'circle', ','), - ('cstring', 2275, 1263, 'cstring', ','), - ('date', 1082, 1182, 'date', ','), - ('daterange', 3912, 3913, 'daterange', ','), - ('event_trigger', 3838, 0, 'event_trigger', ','), - ('float4', 700, 1021, 'real', ','), - ('float8', 701, 1022, 'double precision', ','), - ('gtsvector', 3642, 3644, 'gtsvector', ','), - ('inet', 869, 1041, 'inet', ','), - ('int2', 21, 1005, 'smallint', ','), - ('int2vector', 22, 1006, 'int2vector', ','), - ('int4', 23, 1007, 'integer', ','), - ('int4range', 3904, 3905, 'int4range', ','), - ('int8', 20, 1016, 'bigint', ','), - ('int8range', 3926, 3927, 'int8range', ','), - ('internal', 2281, 0, 'internal', ','), - ('interval', 1186, 1187, 'interval', ','), - ('json', 114, 199, 'json', ','), - ('jsonb', 3802, 3807, 'jsonb', ','), - ('jsonpath', 4072, 4073, 'jsonpath', ','), - ('line', 628, 629, 'line', ','), - ('lseg', 601, 1018, 'lseg', ','), - ('macaddr', 829, 1040, 'macaddr', ','), - ('macaddr8', 774, 775, 'macaddr8', ','), - ('money', 790, 791, 'money', ','), - ('name', 19, 1003, 'name', ','), - ('numeric', 1700, 1231, 'numeric', ','), - ('numrange', 3906, 3907, 'numrange', ','), - ('oid', 26, 1028, 'oid', ','), - ('oidvector', 30, 1013, 'oidvector', ','), - ('opaque', 2282, 0, 'opaque', ','), - ('path', 602, 1019, 'path', ','), - ('point', 600, 1017, 'point', ','), - ('polygon', 604, 1027, 'polygon', ','), - ('record', 2249, 2287, 'record', ','), - ('refcursor', 1790, 2201, 'refcursor', ','), - ('text', 25, 1009, 'text', ','), - ('tid', 27, 1010, 'tid', ','), - ('time', 1083, 1183, 'time without time zone', ','), - ('timestamp', 1114, 1115, 'timestamp without time zone', ','), - ('timestamptz', 1184, 1185, 'timestamp with time zone', ','), - ('timetz', 1266, 1270, 'time with time zone', ','), - ('trigger', 2279, 0, 'trigger', ','), - ('tsquery', 3615, 3645, 'tsquery', ','), - ('tsrange', 3908, 3909, 'tsrange', ','), - ('tstzrange', 3910, 3911, 'tstzrange', ','), - ('tsvector', 3614, 3643, 'tsvector', ','), - ('txid_snapshot', 2970, 2949, 'txid_snapshot', ','), - ('unknown', 705, 0, 'unknown', ','), - ('uuid', 2950, 2951, 'uuid', ','), - ('varbit', 1562, 1563, 'bit varying', ','), - ('varchar', 1043, 1015, 'character varying', ','), - ('void', 2278, 0, 'void', ','), - ('xid', 28, 1011, 'xid', ','), - ('xml', 142, 143, 'xml', ','), - # autogenerated: end - # fmt: on - ] -] - -type_oid: Dict[str, Oid] = {r.name: Oid(r.oid) for r in _oids_table} - -# add aliases too -for r in _oids_table: - if r.alt_name not in type_oid: - type_oid[r.alt_name] = Oid(r.oid) +class TypesInfo: + """ + Container for the information about types in a database. + """ + + def __init__(self) -> None: + self._by_oid: Dict[int, TypeInfo] = {} + self._by_name: Dict[str, TypeInfo] = {} + + def add(self, info: TypeInfo) -> None: + self._by_oid[info.oid] = info + if info.array_oid: + self._by_oid[info.array_oid] = info + self._by_name[info.name] = info + if info.alt_name not in self._by_name: + self._by_name[info.alt_name] = info + + def __getitem__(self, key: Union[str, int]) -> TypeInfo: + if isinstance(key, str): + return self._by_name[key] + elif isinstance(key, int): + return self._by_oid[key] + else: + raise TypeError( + f"the key must be an oid or a name, got {type(key)}" + ) + + def get(self, key: Union[str, int]) -> Optional[TypeInfo]: + try: + return self[key] + except KeyError: + return None + + +builtins = TypesInfo() + +for r in [ + # fmt: off + # autogenerated: start + + # Generated from PostgreSQL 12.2 + + ('aclitem', 1033, 1034, 'aclitem', ','), + ('any', 2276, 0, '"any"', ','), + ('anyarray', 2277, 0, 'anyarray', ','), + ('anyelement', 2283, 0, 'anyelement', ','), + ('anyenum', 3500, 0, 'anyenum', ','), + ('anynonarray', 2776, 0, 'anynonarray', ','), + ('anyrange', 3831, 0, 'anyrange', ','), + ('bit', 1560, 1561, 'bit', ','), + ('bool', 16, 1000, 'boolean', ','), + ('box', 603, 1020, 'box', ';'), + ('bpchar', 1042, 1014, 'character', ','), + ('bytea', 17, 1001, 'bytea', ','), + ('char', 18, 1002, '"char"', ','), + ('cid', 29, 1012, 'cid', ','), + ('cidr', 650, 651, 'cidr', ','), + ('circle', 718, 719, 'circle', ','), + ('cstring', 2275, 1263, 'cstring', ','), + ('date', 1082, 1182, 'date', ','), + ('daterange', 3912, 3913, 'daterange', ','), + ('event_trigger', 3838, 0, 'event_trigger', ','), + ('float4', 700, 1021, 'real', ','), + ('float8', 701, 1022, 'double precision', ','), + ('gtsvector', 3642, 3644, 'gtsvector', ','), + ('inet', 869, 1041, 'inet', ','), + ('int2', 21, 1005, 'smallint', ','), + ('int2vector', 22, 1006, 'int2vector', ','), + ('int4', 23, 1007, 'integer', ','), + ('int4range', 3904, 3905, 'int4range', ','), + ('int8', 20, 1016, 'bigint', ','), + ('int8range', 3926, 3927, 'int8range', ','), + ('internal', 2281, 0, 'internal', ','), + ('interval', 1186, 1187, 'interval', ','), + ('json', 114, 199, 'json', ','), + ('jsonb', 3802, 3807, 'jsonb', ','), + ('jsonpath', 4072, 4073, 'jsonpath', ','), + ('line', 628, 629, 'line', ','), + ('lseg', 601, 1018, 'lseg', ','), + ('macaddr', 829, 1040, 'macaddr', ','), + ('macaddr8', 774, 775, 'macaddr8', ','), + ('money', 790, 791, 'money', ','), + ('name', 19, 1003, 'name', ','), + ('numeric', 1700, 1231, 'numeric', ','), + ('numrange', 3906, 3907, 'numrange', ','), + ('oid', 26, 1028, 'oid', ','), + ('oidvector', 30, 1013, 'oidvector', ','), + ('opaque', 2282, 0, 'opaque', ','), + ('path', 602, 1019, 'path', ','), + ('point', 600, 1017, 'point', ','), + ('polygon', 604, 1027, 'polygon', ','), + ('record', 2249, 2287, 'record', ','), + ('refcursor', 1790, 2201, 'refcursor', ','), + ('text', 25, 1009, 'text', ','), + ('tid', 27, 1010, 'tid', ','), + ('time', 1083, 1183, 'time without time zone', ','), + ('timestamp', 1114, 1115, 'timestamp without time zone', ','), + ('timestamptz', 1184, 1185, 'timestamp with time zone', ','), + ('timetz', 1266, 1270, 'time with time zone', ','), + ('trigger', 2279, 0, 'trigger', ','), + ('tsquery', 3615, 3645, 'tsquery', ','), + ('tsrange', 3908, 3909, 'tsrange', ','), + ('tstzrange', 3910, 3911, 'tstzrange', ','), + ('tsvector', 3614, 3643, 'tsvector', ','), + ('txid_snapshot', 2970, 2949, 'txid_snapshot', ','), + ('unknown', 705, 0, 'unknown', ','), + ('uuid', 2950, 2951, 'uuid', ','), + ('varbit', 1562, 1563, 'bit varying', ','), + ('varchar', 1043, 1015, 'character varying', ','), + ('void', 2278, 0, 'void', ','), + ('xid', 28, 1011, 'xid', ','), + ('xml', 142, 143, 'xml', ','), + # autogenerated: end + # fmt: on +]: + builtins.add(TypeInfo(*r)) def self_update() -> None: @@ -147,7 +172,7 @@ select format( ) new.extend(out.stdout.splitlines()) - new = [b" " * 8 + l if l else b"" for l in new] # indent + new = [b" " * 4 + l if l else b"" for l in new] # indent istart, iend = [ i for i, l in enumerate(lines) diff --git a/psycopg3/types/text.py b/psycopg3/types/text.py index d8327376c..20d473fc2 100644 --- a/psycopg3/types/text.py +++ b/psycopg3/types/text.py @@ -12,9 +12,12 @@ from ..adapt import ( Typecaster, ) from ..connection import BaseConnection -from ..utils.typing import EncodeFunc, DecodeFunc, Oid +from ..utils.typing import EncodeFunc, DecodeFunc from ..pq import Escaping -from .oids import type_oid +from .oids import builtins + +TEXT_OID = builtins["text"].oid +BYTEA_OID = builtins["bytea"].oid @Adapter.text(str) @@ -36,13 +39,13 @@ class StringAdapter(Adapter): return self._encode(obj)[0] -@Typecaster.text(type_oid["text"]) -@Typecaster.binary(type_oid["text"]) +@Typecaster.text(builtins["text"].oid) +@Typecaster.binary(builtins["text"].oid) class StringCaster(Typecaster): decode: Optional[DecodeFunc] - def __init__(self, oid: Oid, conn: BaseConnection): + def __init__(self, oid: int, conn: BaseConnection): super().__init__(oid, conn) if conn is not None: @@ -67,20 +70,20 @@ class BytesAdapter(Adapter): super().__init__(cls, conn) self.esc = Escaping(self.conn.pgconn) - def adapt(self, obj: bytes) -> Tuple[bytes, Oid]: - return self.esc.escape_bytea(obj), type_oid["bytea"] + def adapt(self, obj: bytes) -> Tuple[bytes, int]: + return self.esc.escape_bytea(obj), BYTEA_OID @Adapter.binary(bytes) -def adapt_bytes(b: bytes) -> Tuple[bytes, Oid]: - return b, type_oid["bytea"] +def adapt_bytes(b: bytes) -> Tuple[bytes, int]: + return b, BYTEA_OID -@Typecaster.text(type_oid["bytea"]) +@Typecaster.text(builtins["bytea"].oid) def cast_bytea(data: bytes) -> bytes: return Escaping.unescape_bytea(data) -@Typecaster.binary(type_oid["bytea"]) +@Typecaster.binary(builtins["bytea"].oid) def cast_bytea_binary(data: bytes) -> bytes: return data diff --git a/psycopg3/utils/typing.py b/psycopg3/utils/typing.py index 00506abe8..f96576ce8 100644 --- a/psycopg3/utils/typing.py +++ b/psycopg3/utils/typing.py @@ -4,9 +4,7 @@ Additional types for checking # Copyright (C) 2020 The Psycopg Team -from typing import Any, Callable, Mapping, NewType, Sequence, Tuple, Union - -Oid = NewType("Oid", int) +from typing import Any, Callable, Mapping, Sequence, Tuple, Union EncodeFunc = Callable[[str], Tuple[bytes, int]] DecodeFunc = Callable[[bytes], Tuple[str, int]] diff --git a/tests/test_adapt.py b/tests/test_adapt.py index 1eedca6b7..d1f480fd9 100644 --- a/tests/test_adapt.py +++ b/tests/test_adapt.py @@ -1,6 +1,8 @@ import pytest from psycopg3.adapt import Transformer, Format, Adapter, Typecaster -from psycopg3.types.oids import type_oid +from psycopg3.types.oids import builtins + +TEXT_OID = builtins["text"].oid @pytest.mark.parametrize( @@ -18,7 +20,7 @@ def test_adapt(data, format, result, type): rv = t.adapt(data, format) if isinstance(rv, tuple): assert rv[0] == result - assert rv[1] == type_oid[type] + assert rv[1] == builtins[type].oid else: assert rv == result @@ -60,16 +62,14 @@ def test_adapt_cursor_ctx(conn): ) def test_cast(data, format, type, result): t = Transformer() - rv = t.cast(data, type_oid[type], format) + rv = t.cast(data, builtins[type].oid, format) assert rv == result def test_cast_connection_ctx(conn): - Typecaster.register( - type_oid["text"], lambda b: b.decode("ascii") + "t", conn - ) + Typecaster.register(TEXT_OID, lambda b: b.decode("ascii") + "t", conn) Typecaster.register_binary( - type_oid["text"], lambda b: b.decode("ascii") + "b", conn + TEXT_OID, lambda b: b.decode("ascii") + "b", conn ) r = conn.cursor().execute("select 'hello'::text").fetchone() @@ -79,19 +79,15 @@ def test_cast_connection_ctx(conn): def test_cast_cursor_ctx(conn): - Typecaster.register( - type_oid["text"], lambda b: b.decode("ascii") + "t", conn - ) + Typecaster.register(TEXT_OID, lambda b: b.decode("ascii") + "t", conn) Typecaster.register_binary( - type_oid["text"], lambda b: b.decode("ascii") + "b", conn + TEXT_OID, lambda b: b.decode("ascii") + "b", conn ) cur = conn.cursor() - Typecaster.register( - type_oid["text"], lambda b: b.decode("ascii") + "tc", cur - ) + Typecaster.register(TEXT_OID, lambda b: b.decode("ascii") + "tc", cur) Typecaster.register_binary( - type_oid["text"], lambda b: b.decode("ascii") + "bc", cur + TEXT_OID, lambda b: b.decode("ascii") + "bc", cur ) r = cur.execute("select 'hello'::text").fetchone() diff --git a/tests/types/test_numeric.py b/tests/types/test_numeric.py index 7fd6648d3..99f759d7b 100644 --- a/tests/types/test_numeric.py +++ b/tests/types/test_numeric.py @@ -4,7 +4,7 @@ from math import isnan, isinf, exp import pytest from psycopg3.adapt import Typecaster, Format -from psycopg3.types import type_oid +from psycopg3.types import builtins from psycopg3.types.numeric import cast_float @@ -58,7 +58,7 @@ def test_cast_int(conn, val, pgtype, want, format): cur = conn.cursor(binary=format == Format.BINARY) cur.execute("select %%s::%s" % pgtype, (val,)) assert cur.pgresult.fformat(0) == format - assert cur.pgresult.ftype(0) == type_oid[pgtype] + assert cur.pgresult.ftype(0) == builtins[pgtype].oid result = cur.fetchone()[0] assert result == want assert type(result) is type(want) @@ -209,7 +209,7 @@ def test_roundtrip_numeric(conn, val): ) def test_numeric_as_float(conn, val): cur = conn.cursor() - Typecaster.register(type_oid["numeric"], cast_float, cur) + Typecaster.register(builtins["numeric"].oid, cast_float, cur) val = Decimal(val) cur.execute("select %s", (val,))