# Copyright (C) 2020 The Psycopg Team
import codecs
-from typing import Dict, TYPE_CHECKING
+from typing import Any, Dict, Optional, TYPE_CHECKING
from .errors import NotSupportedError
if TYPE_CHECKING:
from .pq.abc import PGconn
+ from .connection import BaseConnection
_py_codecs = {
"BIG5": "big5",
pg_codecs = {v: k.encode() for k, v in _py_codecs.items()}
+def conn_encoding(conn: "Optional[BaseConnection[Any]]") -> str:
+ """
+ Return the Python encoding name of a psycopg connection.
+
+ Default to utf8 if the connection has no encoding info.
+ """
+ if not conn:
+ return "utf-8"
+ pgenc = conn.pgconn.parameter_status(b"client_encoding") or b"UTF8"
+ return pg2pyenc(pgenc)
+
+
def pgconn_encoding(pgconn: "PGconn") -> str:
"""
- Return the Python encoding name of a connection.
+ Return the Python encoding name of a libpq connection.
Default to utf8 if the connection has no encoding info.
"""
from .sql import Composable
from .abc import Buffer, Query, Params
from ._enums import PyFormat
-from ._encodings import pgconn_encoding
+from ._encodings import conn_encoding
if TYPE_CHECKING:
from .abc import Transformer
self._want_formats: Optional[List[PyFormat]] = None
self.formats: Optional[Sequence[pq.Format]] = None
+ self._encoding = conn_encoding(transformer.connection)
self._parts: List[QueryPart]
self.query = b""
- self._encoding = "utf-8"
self._order: Optional[List[str]] = None
- conn = transformer.connection
- if conn:
- self._encoding = pgconn_encoding(conn.pgconn)
-
def convert(self, query: Query, vars: Optional[Params]) -> None:
"""
Set up the query and parameters to convert.
from .pq import Escaping
from .abc import AdaptContext
from .adapt import Transformer, PyFormat
-from ._encodings import pgconn_encoding
+from ._encodings import conn_encoding
def quote(obj: Any, context: Optional[AdaptContext] = None) -> str:
"""
conn = context.connection if context else None
- enc = pgconn_encoding(conn.pgconn) if conn else "utf-8"
+ enc = conn_encoding(conn)
b = self.as_bytes(context)
if isinstance(b, bytes):
return b.decode(enc)
def as_bytes(self, context: Optional[AdaptContext]) -> bytes:
enc = "utf-8"
if context:
- conn = context.connection
- if conn:
- enc = pgconn_encoding(conn.pgconn)
+ enc = conn_encoding(context.connection)
return self._obj.encode(enc)
def format(self, *args: Any, **kwargs: Any) -> Composed:
if not conn:
raise ValueError("a connection is necessary for Identifier")
esc = Escaping(conn.pgconn)
- enc = pgconn_encoding(conn.pgconn)
+ enc = conn_encoding(conn)
escs = [esc.escape_identifier(s.encode(enc)) for s in self._obj]
return b".".join(escs)
def as_bytes(self, context: Optional[AdaptContext]) -> bytes:
conn = context.connection if context else None
- enc = pgconn_encoding(conn.pgconn) if conn else "utf-8"
+ enc = conn_encoding(conn)
return self.as_string(context).encode(enc)
from ..abc import AdaptContext
from ..adapt import Buffer, Dumper, Loader
from ..errors import DataError
-from .._encodings import pgconn_encoding
+from .._encodings import conn_encoding
if TYPE_CHECKING:
from ..pq.abc import Escaping as EscapingProto
class _BaseStrDumper(Dumper):
-
- _encoding = "utf-8"
-
def __init__(self, cls: type, context: Optional[AdaptContext] = None):
super().__init__(cls, context)
-
- conn = self.connection
- if conn:
- enc = pgconn_encoding(conn.pgconn)
- if enc != "ascii":
- self._encoding = enc
+ enc = conn_encoding(self.connection)
+ self._encoding = enc if enc != "ascii" else "utf-8"
class StrBinaryDumper(_BaseStrDumper):
class TextLoader(Loader):
-
- _encoding = "utf-8"
-
def __init__(self, oid: int, context: Optional[AdaptContext] = None):
super().__init__(oid, context)
- conn = self.connection
- if conn:
- enc = pgconn_encoding(conn.pgconn)
- self._encoding = enc if enc != "ascii" else ""
+ enc = conn_encoding(self.connection)
+ self._encoding = enc if enc != "ascii" else ""
def load(self, data: Buffer) -> Union[bytes, str]:
if self._encoding: