]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
feat: add Column.type_display
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 9 May 2024 01:27:29 +0000 (03:27 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 15 May 2024 15:56:39 +0000 (17:56 +0200)
docs/api/objects.rst
psycopg/psycopg/_column.py
psycopg/psycopg/_typeinfo.py
tests/test_column.py

index 3b285daf76bec201661149a67abeea993f658ca9..33b080835ed7e9b93accc67cd11d14e0cfac83db 100644 (file)
@@ -176,6 +176,10 @@ The description `Column` object
 
     .. autoattribute:: name
     .. autoattribute:: type_code
+    .. autoattribute:: type_display
+
+        .. versionadded:: 3.2
+
     .. autoattribute:: display_size
     .. autoattribute:: internal_size
     .. autoattribute:: precision
index 8be4e44c3dbf4662a2530a423eac2c4d89333c65..7c879a60f12f4a477d0d9f7631a3910d50303e9c 100644 (file)
@@ -40,26 +40,24 @@ class Column(Sequence[Any]):
     def __repr__(self) -> str:
         return (
             f"<Column {self.name!r},"
-            f" type: {self._type_display()} (oid: {self.type_code})>"
+            f" type: {self.type_display} (oid: {self.type_code})>"
         )
 
     def __len__(self) -> int:
         return 7
 
-    def _type_display(self) -> str:
+    @property
+    def type_display(self) -> str:
+        """A pretty representation of the column type.
+
+        It is composed by the type name, followed by eventual modifiers and
+        brackets to signify arrays, e.g. :sql:`text`, :sql:`varchar(42)`,
+        :sql:`date[]`.
+        """
         if not self._type:
             return str(self.type_code)
 
-        parts = []
-        parts.append(self._type.name)
-        mod = self._type.get_modifier(self._fmod)
-        if mod:
-            parts.append(f"({','.join(map(str, mod))})")
-
-        if self.type_code == self._type.array_oid:
-            parts.append("[]")
-
-        return "".join(parts)
+        return self._type.get_type_display(oid=self.type_code, fmod=self._fmod)
 
     def __getitem__(self, index: Any) -> Any:
         if isinstance(index, slice):
@@ -79,7 +77,7 @@ class Column(Sequence[Any]):
 
     @property
     def display_size(self) -> Optional[int]:
-        """The field size, for :sql:`varchar(n)`, None otherwise."""
+        """The field size, for string types such as :sql:`varchar(n)`."""
         return self._type.get_display_size(self._fmod) if self._type else None
 
     @property
index f380cb03564c3c13e279526b23a5ae5c680146e8..27a41a73359a2159e39e04b79f455ec30201c57a 100644 (file)
@@ -194,8 +194,17 @@ ORDER BY t.oid
         """Method called by the `!registry` when the object is added there."""
         pass
 
-    def get_modifier(self, fmod: int) -> tuple[int, ...] | None:
-        return self.typemod.get_modifier(fmod)
+    def get_type_display(self, oid: int | None = None, fmod: int | None = None) -> str:
+        parts = []
+        parts.append(self.name)
+        mod = self.typemod.get_modifier(fmod) if fmod is not None else ()
+        if mod:
+            parts.append(f"({','.join(map(str, mod))})")
+
+        if oid == self.array_oid:
+            parts.append("[]")
+
+        return "".join(parts)
 
     def get_display_size(self, fmod: int) -> int | None:
         return self.typemod.get_display_size(fmod)
index 0440d975620f9f27eaeafeb6633afb22439ba9cb..d5ae58fea832b83bba9e8e25cd5d2d8c1ad3d264 100644 (file)
@@ -66,21 +66,23 @@ def test_description_slice(conn):
     "type, precision, scale, dsize, isize",
     [
         ("text", None, None, None, None),
+        ("text[]", None, None, None, None),
         ("varchar", None, None, None, None),
         ("varchar(1)", None, None, 1, None),
+        ("varchar(1)[]", None, None, 1, None),
         ("varchar(42)", None, None, 42, None),
         ("bpchar(42)", None, None, 42, None),
         ("varchar(10485760)", None, None, 10485760, None),
         ("int4", None, None, None, 4),
         ("numeric", None, None, None, None),
         ("numeric(10,0)", 10, 0, None, None),
-        ("numeric(10,3)", 10, 3, None, None),
+        ("numeric(10,3)[]", 10, 3, None, None),
         ("numeric(10,-1)", 10, -1, None, None),
         ("numeric(1,-1000)", 1, -1000, None, None),
         ("numeric(1,1000)", 1, 1000, None, None),
         ("numeric(1000,1000)", 1000, 1000, None, None),
         ("time", None, None, None, 8),
-        ("time", None, None, None, 8),
+        ("time[]", None, None, None, None),
         ("timetz", None, None, None, 12),
         ("timestamp", None, None, None, 8),
         ("timestamptz", None, None, None, 8),
@@ -98,7 +100,8 @@ def test_details(conn, type, precision, scale, dsize, isize):
     cur = conn.cursor()
     cur.execute(f"select null::{type}")
     col = cur.description[0]
-    assert type in (repr(col))
+    assert type == col.type_display
+    assert f" {type} " in (repr(col))
     assert col.precision == precision
     assert col.scale == scale
     assert col.display_size == dsize