documentation for the generic usage, especially the
`~psycopg.types.TypeInfo.fetch()` method.
- .. attribute:: enum_labels
+ .. attribute:: labels
Contains labels available in the PostgreSQL enum type.
- .. attribute:: python_type
+ .. attribute:: enum
After `register_enum()` is called, it will contain the python type
mapping to the registered enum.
After registering, fetching data of the registered enum will cast
PostgreSQL enum labels into corresponding Python enum labels.
- If no ``python_type`` is specified, a `Enum` is created based on
+ If no `!enum` is specified, a new `Enum` is created based on
PostgreSQL enum labels.
Example::
>>> info = EnumInfo.fetch(conn, "user_role")
>>> register_enum(info, UserRole, conn)
- >>> some_editor = info.python_type.EDITOR
+ >>> some_editor = info.enum.EDITOR
>>> some_editor
<UserRole.EDITOR: 2>
class EnumLoader(Loader, Generic[E]):
_encoding = "utf-8"
- python_type: Type[E]
+ enum: Type[E]
def __init__(self, oid: int, context: Optional[AdaptContext] = None):
super().__init__(oid, context)
else:
label = data.decode(self._encoding)
- return self.python_type[label]
+ return self.enum[label]
class EnumBinaryLoader(EnumLoader[E]):
def register_enum(
info: EnumInfo,
- python_type: Optional[Type[E]] = None,
+ enum: Optional[Type[E]] = None,
context: Optional[AdaptContext] = None,
) -> None:
"""Register the adapters to load and dump a enum type.
:param info: The object with the information about the enum to register.
- :param python_type: Python enum type matching to the Postgres one. If `!None`,
- the type will be generated and put into info.python_type.
+ :param enum: Python enum type matching to the Postgres one. If `!None`,
+ a new enum will be generated and exposed as `EnumInfo.enum`.
:param context: The context where to register the adapters. If `!None`,
register it globally.
"""
if not info:
raise TypeError("no info passed. Is the requested enum available?")
- if python_type is None:
- python_type = cast(
- Type[E],
- Enum(info.name.title(), {label: label for label in info.enum_labels}),
- )
+ if enum is None:
+ enum = cast(Type[E], Enum(info.name.title(), info.labels, module=__name__))
- info.python_type = python_type
+ info.enum = enum
adapters = context.adapters if context else postgres.adapters
info.register(context)
- attribs: Dict[str, Any] = {"python_type": info.python_type}
+ attribs: Dict[str, Any] = {"enum": info.enum}
loader_base = EnumLoader
- name = f"{info.name.title()}{loader_base.__name__}"
+ name = f"{info.name.title()}Loader"
loader = type(name, (loader_base,), attribs)
adapters.register_loader(info.oid, loader)
loader_base = EnumBinaryLoader
- name = f"{info.name.title()}{loader_base.__name__}"
+ name = f"{info.name.title()}BinaryLoader"
loader = type(name, (loader_base,), attribs)
adapters.register_loader(info.oid, loader)
attribs = {"oid": info.oid}
- dumper_base: Type[Dumper] = EnumBinaryDumper
- name = f"{info.name.title()}{dumper_base.__name__}"
- dumper = type(name, (dumper_base,), attribs)
- adapters.register_dumper(info.python_type, dumper)
+ name = f"{enum.__name__}BinaryDumper"
+ dumper = type(name, (EnumBinaryDumper,), attribs)
+ adapters.register_dumper(info.enum, dumper)
- dumper_base = EnumDumper
- name = f"{info.name.title()}{dumper_base.__name__}"
- dumper = type(name, (dumper_base,), attribs)
- adapters.register_dumper(info.python_type, dumper)
+ name = f"{enum.__name__}Dumper"
+ dumper = type(name, (EnumDumper,), attribs)
+ adapters.register_dumper(info.enum, dumper)
def register_default_adapters(context: AdaptContext) -> None:
assert info.name == name
assert info.oid > 0
assert info.oid != info.array_oid > 0
- assert len(info.enum_labels) == len(labels)
- assert info.enum_labels == labels
+ assert len(info.labels) == len(labels)
+ assert info.labels == labels
def test_register_makes_a_type(conn, testenum):
name, enum, labels = testenum
info = EnumInfo.fetch(conn, name)
assert info
- assert info.python_type is None
+ assert info.enum is None
register_enum(info, context=conn)
- assert info.python_type is not None
- assert [e.name for e in info.python_type] == [e.name for e in enum]
+ assert info.enum is not None
+ assert [e.name for e in info.enum] == [e.name for e in enum]
@pytest.mark.parametrize("encoding", encodings)
for label in labels:
cur = conn.execute(f"select %{fmt_in}::{name}", [label], binary=fmt_out)
- assert cur.fetchone()[0] == info.python_type(label)
+ assert cur.fetchone()[0] == info.enum(label)
@pytest.mark.parametrize("encoding", encodings)
register_enum(info, enum, conn)
cur = conn.execute(f"select %{fmt_in}::{name}[]", [labels], binary=fmt_out)
- assert cur.fetchone()[0] == list(info.python_type)
+ assert cur.fetchone()[0] == list(info.enum)
@pytest.mark.asyncio
assert info.name == name
assert info.oid > 0
assert info.oid != info.array_oid > 0
- assert len(info.enum_labels) == len(labels)
- assert info.enum_labels == labels
+ assert len(info.labels) == len(labels)
+ assert info.labels == labels
@pytest.mark.asyncio