]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Added object to map oid and data types
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 3 Apr 2020 00:27:59 +0000 (13:27 +1300)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 3 Apr 2020 11:16:06 +0000 (00:16 +1300)
psycopg3/adapt.py
psycopg3/pq/pq_ctypes.py
psycopg3/types/__init__.py
psycopg3/types/numeric.py
psycopg3/types/oids.py
psycopg3/types/text.py
psycopg3/utils/typing.py
tests/test_adapt.py
tests/types/test_numeric.py

index b25b4894ec500aa607b675d6a497d2f1ad249adc..fec5e3dc93b8d1d3618670ae6a9940660bbad104 100644 (file)
@@ -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:
index 66030151b47fbf81af621d728b2aaaf838f51511..626275ed4ff66502839b4e767457b1375292b3ff 100644 (file)
@@ -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:
index c988c0fdb0cd1863b4a85d3e40efdcc052d72b3a..5dbaf107354a695674c92c55f19e3b3312b69aef 100644 (file)
@@ -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"]
index efb6b46a1e0ef141e1ea40746fe6ed729f8b616d..9b22a2bb6a30a101baf904a2a28cfc8c39d1b272 100644 (file)
@@ -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]
index 2ec524bfc5cc9b35d9eb37782ab1b6c88996ffd8..95bdb2a5bcfc123cf3ca3f7f534e1960199bee1d 100644 (file)
@@ -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)
index d8327376c88e1b4cafb5e584993df8e390c37e6f..20d473fc259a1eb4c33a18d7af561b63debfc9dd 100644 (file)
@@ -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
index 00506abe8107427a47502a64024cd86da8cb65fe..f96576ce88be3b98c309c42ec84cd341c91bf66b 100644 (file)
@@ -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]]
index 1eedca6b7d6b8adef1a32cb4105cdd199df81cdf..d1f480fd9ea839756588e7c34f67e57241ed3a7d 100644 (file)
@@ -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()
index 7fd6648d3789e6a016c97e529ab68f46b3b01097..99f759d7b9f4ba04358304e7d8246ca0dcb7ab84 100644 (file)
@@ -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,))