From: Daniele Varrazzo Date: Sat, 28 Mar 2020 11:50:19 +0000 (+1300) Subject: Added register_adapter/caster functions X-Git-Tag: 3.0.dev0~661 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8eab430f107861cc7055e5ba488eeb82278c434;p=thirdparty%2Fpsycopg.git Added register_adapter/caster functions --- diff --git a/psycopg3/adaptation.py b/psycopg3/adaptation.py index 5bb1b4096..293a47d00 100644 --- a/psycopg3/adaptation.py +++ b/psycopg3/adaptation.py @@ -8,6 +8,8 @@ import codecs from . import exceptions as exc from .pq import Format +from .cursor import BaseCursor +from .connection import BaseConnection INVALID_OID = 0 TEXT_OID = 25 @@ -21,9 +23,44 @@ global_adapters = {} global_casters = {} -class ValuesTransformer: +def register_adapter(cls, adapter, context=None, format=Format.TEXT): + + if context is not None and not isinstance( + context, (BaseConnection, BaseCursor) + ): + raise TypeError( + f"the context should be a connection or cursor;" + f" got {type(context).__name__}" + ) + + where = context.adapters if context is not None else global_adapters + where[cls, format] = adapter + + +def register_binary_adapter(cls, adapter, context=None): + register_adapter(cls, adapter, context, format=Format.BINARY) + + +def register_caster(oid, caster, context=None, format=Format.TEXT): + if context is not None and not isinstance( + context, (BaseConnection, BaseCursor) + ): + raise TypeError( + f"the context should be a connection or cursor;" + f" got {type(context).__name__}" + ) + + where = context.adapters if context is not None else global_casters + where[oid, format] = caster + + +def register_binary_caster(oid, caster, context=None): + register_caster(oid, caster, context, format=Format.BINARY) + + +class Transformer: """ - An object that can adapt efficiently a number of value. + An object that can adapt efficiently between Python and PostgreSQL. The life cycle of the object is the query, so it is assumed that stuff like the server version or connection encoding will not change. It can have its @@ -31,9 +68,6 @@ class ValuesTransformer: """ def __init__(self, context): - from .connection import BaseConnection - from .cursor import BaseCursor - if context is None: self.connection = None self.cursor = None @@ -217,10 +251,11 @@ class StringCaster(Typecaster): return data -global_adapters[str, Format.TEXT] = StringAdapter -global_adapters[str, Format.BINARY] = StringAdapter -global_casters[TEXT_OID, Format.TEXT] = StringCaster -global_casters[TEXT_OID, Format.BINARY] = StringCaster +register_adapter(str, StringAdapter) +register_binary_adapter(str, StringAdapter) + +register_caster(TEXT_OID, StringCaster) +register_binary_caster(TEXT_OID, StringCaster) def adapt_int(obj): @@ -231,8 +266,8 @@ def cast_int(data): return int(ascii_decode(data)[0]) -global_adapters[int, Format.TEXT] = adapt_int -global_casters[NUMERIC_OID, Format.TEXT] = cast_int +register_adapter(int, adapt_int) +register_caster(NUMERIC_OID, cast_int) class UnknownCaster(Typecaster): @@ -255,5 +290,5 @@ def binary_cast_unknown(data): return data -global_casters[INVALID_OID, Format.TEXT] = UnknownCaster -global_casters[INVALID_OID, Format.BINARY] = binary_cast_unknown +register_caster(INVALID_OID, UnknownCaster) +register_binary_caster(INVALID_OID, binary_cast_unknown) diff --git a/psycopg3/cursor.py b/psycopg3/cursor.py index d92c16b16..e5d63f1f9 100644 --- a/psycopg3/cursor.py +++ b/psycopg3/cursor.py @@ -6,7 +6,6 @@ psycopg3 cursor objects from . import exceptions as exc from .pq import error_message, DiagnosticField, ExecStatus -from .adaptation import ValuesTransformer from .utils.queries import query2pg, reorder_params @@ -19,11 +18,13 @@ class BaseCursor: self._reset() def _reset(self): + from .adaptation import Transformer + self._results = [] self._result = None self._pos = 0 self._iresult = 0 - self._transformer = ValuesTransformer(self) + self._transformer = Transformer(self) def _execute_send(self, query, vars): # Implement part of execute() before waiting common to sync and async