We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
If PK of table is a UUID, table wont render
## Description
<!-- A clear and concise description of what the bug is. -->
If PK of table is a UUID, table wont render

## Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
Table should render

## To Reproduce
<!-- How can we recreate this bug? Please try to provide a Minimal, Complete, and Verifiable (http://stackoverflow.com/help/mcve) example if code-related. -->
Create a table where PK is a UUID in postgres
## Environment
 - OS: (_eg._ macOS 10.14.6; Fedora 32)
 - Browser: (_eg._ Safari; Firefox)
 - Browser Version: (_eg._ 13; 73)
 - Other info:

## Additional context
<!-- Add any other context about the problem or screenshots here. -->
![image](https://user-images.githubusercontent.com/49372179/222764488-03a78062-e3d7-40f8-99c1-2e992df3c0bf.png)
![image](https://user-images.githubusercontent.com/49372179/222764618-b92138b5-7de4-4ea6-bf6b-cfd362085935.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `db/columns/base.py`
Content:
```
1 from sqlalchemy import Column, ForeignKey, inspect
2 
3 from db.columns.defaults import TYPE, PRIMARY_KEY, NULLABLE, DEFAULT_COLUMNS
4 from db.columns.operations.select import (
5     get_column_attnum_from_name, get_column_default, get_column_default_dict,
6 )
7 from db.tables.operations.select import get_oid_from_table
8 from db.types.operations.cast import get_full_cast_map
9 from db.types.operations.convert import get_db_type_enum_from_class
10 
11 
12 # TODO consider renaming to DbColumn or DatabaseColumn
13 # We are attempting to reserve the term Mathesar for types in the mathesar namespace.
14 class MathesarColumn(Column):
15     """
16     This class constrains the possible arguments, enabling us to include
17     a copy method (which has been deprecated in upstream SQLAlchemy since
18     1.4).  The idea is that we can faithfully copy the subset of the
19     column definition that we care about, and this class defines that
20     subset.
21     """
22 
23     def __init__(
24             self,
25             name,
26             sa_type,
27             foreign_keys=None,
28             primary_key=False,
29             nullable=True,
30             autoincrement=False,
31             server_default=None,
32             engine=None,
33     ):
34         """
35         Construct a new ``MathesarColumn`` object.
36 
37         Required arguments:
38         name -- String giving the name of the column in the database.
39         sa_type -- the SQLAlchemy type of the column.
40 
41         Optional keyword arguments:
42         primary_key -- Boolean giving whether the column is a primary key.
43         nullable -- Boolean giving whether the column is nullable.
44         server_default -- String or DefaultClause giving the default value
45         """
46         if foreign_keys is None:
47             foreign_keys = set()
48         self.engine = engine
49         super().__init__(
50             *foreign_keys,
51             name=name,
52             type_=sa_type,
53             primary_key=primary_key,
54             nullable=nullable,
55             autoincrement=autoincrement,
56             server_default=server_default
57         )
58         # NOTE: For some reason, sometimes `self._proxies` is a tuple. SA expects it to be
59         # appendable, however. Was not able to track down the source of it. As a workaround, we
60         # convert it into a list here. I (Dom) offer a bounty of bragging rights to anyone who
61         # figures out what's causing `_proxies` to be tuples.
62         if isinstance(self._proxies, tuple):
63             self._proxies = list(self._proxies)
64 
65     @classmethod
66     def _constructor(cls, *args, **kwargs):
67         """
68         Needed to support Column.copy().
69 
70         See https://docs.sqlalchemy.org/en/14/changelog/changelog_07.html?highlight=_constructor#change-de8c32a6729c83da17177f6a13979717
71         """
72         return MathesarColumn.from_column(
73             Column(*args, **kwargs)
74         )
75 
76     @classmethod
77     def from_column(cls, column, engine=None):
78         """
79         This alternate init method creates a new column (a copy) of the
80         given column.  It respects only the properties in the __init__
81         of the MathesarColumn.
82         """
83         try:
84             fkeys = {ForeignKey(fk.target_fullname) for fk in column.foreign_keys}
85             new_column = cls(
86                 column.name,
87                 column.type,
88                 foreign_keys=fkeys,
89                 primary_key=column.primary_key,
90                 nullable=column.nullable,
91                 autoincrement=column.autoincrement,
92                 server_default=column.server_default,
93                 engine=engine,
94             )
95             new_column.original_table = column.table
96         # dirty hack to handle cases where this isn't a real column
97         except AttributeError:
98             new_column = cls(
99                 column.name,
100                 column.type,
101                 engine=engine,
102             )
103         return new_column
104 
105     def to_sa_column(self):
106         """
107         MathesarColumn sometimes is not interchangeable with SQLAlchemy's Column.
108         For use in those situations, this method attempts to recreate an SA Column.
109 
110         NOTE: this method is incomplete: it does not account for all properties of MathesarColumn.
111         """
112         sa_column = Column(name=self.name, type_=self.type)
113         sa_column.table = self.table_
114         return sa_column
115 
116     @property
117     def table_(self):
118         """
119         Returns the current table the column is associated with if it exists, otherwise
120         returns the table the column was originally created from.
121         """
122         if hasattr(self, "table") and self.table is not None:
123             return self.table
124         elif hasattr(self, "original_table") and self.original_table is not None:
125             return self.original_table
126         return None
127 
128     @property
129     def table_oid(self):
130         if self.table_ is not None:
131             oid = get_oid_from_table(
132                 self.table_.name, self.table_.schema, self.engine
133             )
134         else:
135             oid = None
136         return oid
137 
138     @property
139     def is_default(self):
140         default_def = DEFAULT_COLUMNS.get(self.name, False)
141         return (
142             default_def
143             and self.type.python_type == default_def[TYPE]().python_type
144             and self.primary_key == default_def.get(PRIMARY_KEY, False)
145             and self.nullable == default_def.get(NULLABLE, True)
146         )
147 
148     def add_engine(self, engine):
149         self.engine = engine
150 
151     @property
152     def valid_target_types(self):
153         """
154         Returns a set of valid types to which the type of the column can be
155         altered.
156         """
157         if (
158             self.engine is not None
159             and not self.is_default
160             and self.db_type is not None
161         ):
162             db_type = self.db_type
163             valid_target_types = sorted(
164                 list(
165                     set(
166                         get_full_cast_map(self.engine).get(db_type, [])
167                     )
168                 ),
169                 key=lambda db_type: db_type.id
170             )
171             return valid_target_types if valid_target_types else None
172 
173     @property
174     def column_attnum(self):
175         """
176         Get the attnum of this column in its table, if it is
177         attached to a table that is associated with the column's engine.
178         """
179         engine_exists = self.engine is not None
180         table_exists = self.table_ is not None
181         # TODO are we checking here that the table exists on the database? explain why we have to do
182         # that.
183         engine_has_table = inspect(self.engine).has_table(
184             self.table_.name,
185             schema=self.table_.schema,
186         )
187         if engine_exists and table_exists and engine_has_table:
188             metadata = self.table_.metadata
189             return get_column_attnum_from_name(
190                 self.table_oid,
191                 self.name,
192                 self.engine,
193                 metadata=metadata,
194             )
195 
196     @property
197     def column_default_dict(self):
198         if self.table_ is None:
199             return
200         metadata = self.table_.metadata
201         default_dict = get_column_default_dict(
202             self.table_oid, self.column_attnum, self.engine, metadata=metadata,
203         )
204         if default_dict:
205             return {
206                 'is_dynamic': default_dict['is_dynamic'],
207                 'value': default_dict['value']
208             }
209 
210     @property
211     def default_value(self):
212         if self.table_ is not None:
213             metadata = self.table_.metadata
214             return get_column_default(
215                 self.table_oid,
216                 self.column_attnum,
217                 self.engine,
218                 metadata=metadata,
219             )
220 
221     @property
222     def db_type(self):
223         """
224         Get this column's database type enum.
225         """
226         self._assert_that_engine_is_present()
227         return get_db_type_enum_from_class(self.type.__class__)
228 
229     @property
230     def type_options(self):
231         item_type = getattr(self.type, "item_type", None)
232         if item_type is not None:
233             item_type_name = get_db_type_enum_from_class(item_type.__class__).id
234         else:
235             item_type_name = None
236         full_type_options = {
237             "length": getattr(self.type, "length", None),
238             "precision": getattr(self.type, "precision", None),
239             "scale": getattr(self.type, "scale", None),
240             "fields": getattr(self.type, "fields", None),
241             "item_type": item_type_name,
242             "dimensions": getattr(self.type, "dimensions", None)
243         }
244         _type_options = {k: v for k, v in full_type_options.items() if v is not None}
245         return _type_options if _type_options else None
246 
247     def _assert_that_engine_is_present(self):
248         if self.engine is None:
249             raise Exception("Engine should not be None.")
250
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/db/columns/base.py b/db/columns/base.py
--- a/db/columns/base.py
+++ b/db/columns/base.py
@@ -138,6 +138,10 @@
     @property
     def is_default(self):
         default_def = DEFAULT_COLUMNS.get(self.name, False)
+        try:
+            self.type.python_type
+        except NotImplementedError:
+            return False
         return (
             default_def
             and self.type.python_type == default_def[TYPE]().python_type

{"golden_diff": "diff --git a/db/columns/base.py b/db/columns/base.py\n--- a/db/columns/base.py\n+++ b/db/columns/base.py\n@@ -138,6 +138,10 @@\n     @property\n     def is_default(self):\n         default_def = DEFAULT_COLUMNS.get(self.name, False)\n+        try:\n+            self.type.python_type\n+        except NotImplementedError:\n+            return False\n         return (\n             default_def\n             and self.type.python_type == default_def[TYPE]().python_type\n", "issue": "If PK of table is a UUID, table wont render\n## Description\r\n<!-- A clear and concise description of what the bug is. -->\r\nIf PK of table is a UUID, table wont render\r\n\r\n## Expected behavior\r\n<!-- A clear and concise description of what you expected to happen. -->\r\nTable should render\r\n\r\n## To Reproduce\r\n<!-- How can we recreate this bug? Please try to provide a Minimal, Complete, and Verifiable (http://stackoverflow.com/help/mcve) example if code-related. -->\r\nCreate a table where PK is a UUID in postgres\r\n## Environment\r\n - OS: (_eg._ macOS 10.14.6; Fedora 32)\r\n - Browser: (_eg._ Safari; Firefox)\r\n - Browser Version: (_eg._ 13; 73)\r\n - Other info:\r\n\r\n## Additional context\r\n<!-- Add any other context about the problem or screenshots here. -->\r\n![image](https://user-images.githubusercontent.com/49372179/222764488-03a78062-e3d7-40f8-99c1-2e992df3c0bf.png)\r\n![image](https://user-images.githubusercontent.com/49372179/222764618-b92138b5-7de4-4ea6-bf6b-cfd362085935.png)\r\n\n", "before_files": [{"content": "from sqlalchemy import Column, ForeignKey, inspect\n\nfrom db.columns.defaults import TYPE, PRIMARY_KEY, NULLABLE, DEFAULT_COLUMNS\nfrom db.columns.operations.select import (\n    get_column_attnum_from_name, get_column_default, get_column_default_dict,\n)\nfrom db.tables.operations.select import get_oid_from_table\nfrom db.types.operations.cast import get_full_cast_map\nfrom db.types.operations.convert import get_db_type_enum_from_class\n\n\n# TODO consider renaming to DbColumn or DatabaseColumn\n# We are attempting to reserve the term Mathesar for types in the mathesar namespace.\nclass MathesarColumn(Column):\n    \"\"\"\n    This class constrains the possible arguments, enabling us to include\n    a copy method (which has been deprecated in upstream SQLAlchemy since\n    1.4).  The idea is that we can faithfully copy the subset of the\n    column definition that we care about, and this class defines that\n    subset.\n    \"\"\"\n\n    def __init__(\n            self,\n            name,\n            sa_type,\n            foreign_keys=None,\n            primary_key=False,\n            nullable=True,\n            autoincrement=False,\n            server_default=None,\n            engine=None,\n    ):\n        \"\"\"\n        Construct a new ``MathesarColumn`` object.\n\n        Required arguments:\n        name -- String giving the name of the column in the database.\n        sa_type -- the SQLAlchemy type of the column.\n\n        Optional keyword arguments:\n        primary_key -- Boolean giving whether the column is a primary key.\n        nullable -- Boolean giving whether the column is nullable.\n        server_default -- String or DefaultClause giving the default value\n        \"\"\"\n        if foreign_keys is None:\n            foreign_keys = set()\n        self.engine = engine\n        super().__init__(\n            *foreign_keys,\n            name=name,\n            type_=sa_type,\n            primary_key=primary_key,\n            nullable=nullable,\n            autoincrement=autoincrement,\n            server_default=server_default\n        )\n        # NOTE: For some reason, sometimes `self._proxies` is a tuple. SA expects it to be\n        # appendable, however. Was not able to track down the source of it. As a workaround, we\n        # convert it into a list here. I (Dom) offer a bounty of bragging rights to anyone who\n        # figures out what's causing `_proxies` to be tuples.\n        if isinstance(self._proxies, tuple):\n            self._proxies = list(self._proxies)\n\n    @classmethod\n    def _constructor(cls, *args, **kwargs):\n        \"\"\"\n        Needed to support Column.copy().\n\n        See https://docs.sqlalchemy.org/en/14/changelog/changelog_07.html?highlight=_constructor#change-de8c32a6729c83da17177f6a13979717\n        \"\"\"\n        return MathesarColumn.from_column(\n            Column(*args, **kwargs)\n        )\n\n    @classmethod\n    def from_column(cls, column, engine=None):\n        \"\"\"\n        This alternate init method creates a new column (a copy) of the\n        given column.  It respects only the properties in the __init__\n        of the MathesarColumn.\n        \"\"\"\n        try:\n            fkeys = {ForeignKey(fk.target_fullname) for fk in column.foreign_keys}\n            new_column = cls(\n                column.name,\n                column.type,\n                foreign_keys=fkeys,\n                primary_key=column.primary_key,\n                nullable=column.nullable,\n                autoincrement=column.autoincrement,\n                server_default=column.server_default,\n                engine=engine,\n            )\n            new_column.original_table = column.table\n        # dirty hack to handle cases where this isn't a real column\n        except AttributeError:\n            new_column = cls(\n                column.name,\n                column.type,\n                engine=engine,\n            )\n        return new_column\n\n    def to_sa_column(self):\n        \"\"\"\n        MathesarColumn sometimes is not interchangeable with SQLAlchemy's Column.\n        For use in those situations, this method attempts to recreate an SA Column.\n\n        NOTE: this method is incomplete: it does not account for all properties of MathesarColumn.\n        \"\"\"\n        sa_column = Column(name=self.name, type_=self.type)\n        sa_column.table = self.table_\n        return sa_column\n\n    @property\n    def table_(self):\n        \"\"\"\n        Returns the current table the column is associated with if it exists, otherwise\n        returns the table the column was originally created from.\n        \"\"\"\n        if hasattr(self, \"table\") and self.table is not None:\n            return self.table\n        elif hasattr(self, \"original_table\") and self.original_table is not None:\n            return self.original_table\n        return None\n\n    @property\n    def table_oid(self):\n        if self.table_ is not None:\n            oid = get_oid_from_table(\n                self.table_.name, self.table_.schema, self.engine\n            )\n        else:\n            oid = None\n        return oid\n\n    @property\n    def is_default(self):\n        default_def = DEFAULT_COLUMNS.get(self.name, False)\n        return (\n            default_def\n            and self.type.python_type == default_def[TYPE]().python_type\n            and self.primary_key == default_def.get(PRIMARY_KEY, False)\n            and self.nullable == default_def.get(NULLABLE, True)\n        )\n\n    def add_engine(self, engine):\n        self.engine = engine\n\n    @property\n    def valid_target_types(self):\n        \"\"\"\n        Returns a set of valid types to which the type of the column can be\n        altered.\n        \"\"\"\n        if (\n            self.engine is not None\n            and not self.is_default\n            and self.db_type is not None\n        ):\n            db_type = self.db_type\n            valid_target_types = sorted(\n                list(\n                    set(\n                        get_full_cast_map(self.engine).get(db_type, [])\n                    )\n                ),\n                key=lambda db_type: db_type.id\n            )\n            return valid_target_types if valid_target_types else None\n\n    @property\n    def column_attnum(self):\n        \"\"\"\n        Get the attnum of this column in its table, if it is\n        attached to a table that is associated with the column's engine.\n        \"\"\"\n        engine_exists = self.engine is not None\n        table_exists = self.table_ is not None\n        # TODO are we checking here that the table exists on the database? explain why we have to do\n        # that.\n        engine_has_table = inspect(self.engine).has_table(\n            self.table_.name,\n            schema=self.table_.schema,\n        )\n        if engine_exists and table_exists and engine_has_table:\n            metadata = self.table_.metadata\n            return get_column_attnum_from_name(\n                self.table_oid,\n                self.name,\n                self.engine,\n                metadata=metadata,\n            )\n\n    @property\n    def column_default_dict(self):\n        if self.table_ is None:\n            return\n        metadata = self.table_.metadata\n        default_dict = get_column_default_dict(\n            self.table_oid, self.column_attnum, self.engine, metadata=metadata,\n        )\n        if default_dict:\n            return {\n                'is_dynamic': default_dict['is_dynamic'],\n                'value': default_dict['value']\n            }\n\n    @property\n    def default_value(self):\n        if self.table_ is not None:\n            metadata = self.table_.metadata\n            return get_column_default(\n                self.table_oid,\n                self.column_attnum,\n                self.engine,\n                metadata=metadata,\n            )\n\n    @property\n    def db_type(self):\n        \"\"\"\n        Get this column's database type enum.\n        \"\"\"\n        self._assert_that_engine_is_present()\n        return get_db_type_enum_from_class(self.type.__class__)\n\n    @property\n    def type_options(self):\n        item_type = getattr(self.type, \"item_type\", None)\n        if item_type is not None:\n            item_type_name = get_db_type_enum_from_class(item_type.__class__).id\n        else:\n            item_type_name = None\n        full_type_options = {\n            \"length\": getattr(self.type, \"length\", None),\n            \"precision\": getattr(self.type, \"precision\", None),\n            \"scale\": getattr(self.type, \"scale\", None),\n            \"fields\": getattr(self.type, \"fields\", None),\n            \"item_type\": item_type_name,\n            \"dimensions\": getattr(self.type, \"dimensions\", None)\n        }\n        _type_options = {k: v for k, v in full_type_options.items() if v is not None}\n        return _type_options if _type_options else None\n\n    def _assert_that_engine_is_present(self):\n        if self.engine is None:\n            raise Exception(\"Engine should not be None.\")\n", "path": "db/columns/base.py"}], "after_files": [{"content": "from sqlalchemy import Column, ForeignKey, inspect\n\nfrom db.columns.defaults import TYPE, PRIMARY_KEY, NULLABLE, DEFAULT_COLUMNS\nfrom db.columns.operations.select import (\n    get_column_attnum_from_name, get_column_default, get_column_default_dict,\n)\nfrom db.tables.operations.select import get_oid_from_table\nfrom db.types.operations.cast import get_full_cast_map\nfrom db.types.operations.convert import get_db_type_enum_from_class\n\n\n# TODO consider renaming to DbColumn or DatabaseColumn\n# We are attempting to reserve the term Mathesar for types in the mathesar namespace.\nclass MathesarColumn(Column):\n    \"\"\"\n    This class constrains the possible arguments, enabling us to include\n    a copy method (which has been deprecated in upstream SQLAlchemy since\n    1.4).  The idea is that we can faithfully copy the subset of the\n    column definition that we care about, and this class defines that\n    subset.\n    \"\"\"\n\n    def __init__(\n            self,\n            name,\n            sa_type,\n            foreign_keys=None,\n            primary_key=False,\n            nullable=True,\n            autoincrement=False,\n            server_default=None,\n            engine=None,\n    ):\n        \"\"\"\n        Construct a new ``MathesarColumn`` object.\n\n        Required arguments:\n        name -- String giving the name of the column in the database.\n        sa_type -- the SQLAlchemy type of the column.\n\n        Optional keyword arguments:\n        primary_key -- Boolean giving whether the column is a primary key.\n        nullable -- Boolean giving whether the column is nullable.\n        server_default -- String or DefaultClause giving the default value\n        \"\"\"\n        if foreign_keys is None:\n            foreign_keys = set()\n        self.engine = engine\n        super().__init__(\n            *foreign_keys,\n            name=name,\n            type_=sa_type,\n            primary_key=primary_key,\n            nullable=nullable,\n            autoincrement=autoincrement,\n            server_default=server_default\n        )\n        # NOTE: For some reason, sometimes `self._proxies` is a tuple. SA expects it to be\n        # appendable, however. Was not able to track down the source of it. As a workaround, we\n        # convert it into a list here. I (Dom) offer a bounty of bragging rights to anyone who\n        # figures out what's causing `_proxies` to be tuples.\n        if isinstance(self._proxies, tuple):\n            self._proxies = list(self._proxies)\n\n    @classmethod\n    def _constructor(cls, *args, **kwargs):\n        \"\"\"\n        Needed to support Column.copy().\n\n        See https://docs.sqlalchemy.org/en/14/changelog/changelog_07.html?highlight=_constructor#change-de8c32a6729c83da17177f6a13979717\n        \"\"\"\n        return MathesarColumn.from_column(\n            Column(*args, **kwargs)\n        )\n\n    @classmethod\n    def from_column(cls, column, engine=None):\n        \"\"\"\n        This alternate init method creates a new column (a copy) of the\n        given column.  It respects only the properties in the __init__\n        of the MathesarColumn.\n        \"\"\"\n        try:\n            fkeys = {ForeignKey(fk.target_fullname) for fk in column.foreign_keys}\n            new_column = cls(\n                column.name,\n                column.type,\n                foreign_keys=fkeys,\n                primary_key=column.primary_key,\n                nullable=column.nullable,\n                autoincrement=column.autoincrement,\n                server_default=column.server_default,\n                engine=engine,\n            )\n            new_column.original_table = column.table\n        # dirty hack to handle cases where this isn't a real column\n        except AttributeError:\n            new_column = cls(\n                column.name,\n                column.type,\n                engine=engine,\n            )\n        return new_column\n\n    def to_sa_column(self):\n        \"\"\"\n        MathesarColumn sometimes is not interchangeable with SQLAlchemy's Column.\n        For use in those situations, this method attempts to recreate an SA Column.\n\n        NOTE: this method is incomplete: it does not account for all properties of MathesarColumn.\n        \"\"\"\n        sa_column = Column(name=self.name, type_=self.type)\n        sa_column.table = self.table_\n        return sa_column\n\n    @property\n    def table_(self):\n        \"\"\"\n        Returns the current table the column is associated with if it exists, otherwise\n        returns the table the column was originally created from.\n        \"\"\"\n        if hasattr(self, \"table\") and self.table is not None:\n            return self.table\n        elif hasattr(self, \"original_table\") and self.original_table is not None:\n            return self.original_table\n        return None\n\n    @property\n    def table_oid(self):\n        if self.table_ is not None:\n            oid = get_oid_from_table(\n                self.table_.name, self.table_.schema, self.engine\n            )\n        else:\n            oid = None\n        return oid\n\n    @property\n    def is_default(self):\n        default_def = DEFAULT_COLUMNS.get(self.name, False)\n        try:\n            self.type.python_type\n        except NotImplementedError:\n            return False\n        return (\n            default_def\n            and self.type.python_type == default_def[TYPE]().python_type\n            and self.primary_key == default_def.get(PRIMARY_KEY, False)\n            and self.nullable == default_def.get(NULLABLE, True)\n        )\n\n    def add_engine(self, engine):\n        self.engine = engine\n\n    @property\n    def valid_target_types(self):\n        \"\"\"\n        Returns a set of valid types to which the type of the column can be\n        altered.\n        \"\"\"\n        if (\n            self.engine is not None\n            and not self.is_default\n            and self.db_type is not None\n        ):\n            db_type = self.db_type\n            valid_target_types = sorted(\n                list(\n                    set(\n                        get_full_cast_map(self.engine).get(db_type, [])\n                    )\n                ),\n                key=lambda db_type: db_type.id\n            )\n            return valid_target_types if valid_target_types else None\n\n    @property\n    def column_attnum(self):\n        \"\"\"\n        Get the attnum of this column in its table, if it is\n        attached to a table that is associated with the column's engine.\n        \"\"\"\n        engine_exists = self.engine is not None\n        table_exists = self.table_ is not None\n        # TODO are we checking here that the table exists on the database? explain why we have to do\n        # that.\n        engine_has_table = inspect(self.engine).has_table(\n            self.table_.name,\n            schema=self.table_.schema,\n        )\n        if engine_exists and table_exists and engine_has_table:\n            metadata = self.table_.metadata\n            return get_column_attnum_from_name(\n                self.table_oid,\n                self.name,\n                self.engine,\n                metadata=metadata,\n            )\n\n    @property\n    def column_default_dict(self):\n        if self.table_ is None:\n            return\n        metadata = self.table_.metadata\n        default_dict = get_column_default_dict(\n            self.table_oid, self.column_attnum, self.engine, metadata=metadata,\n        )\n        if default_dict:\n            return {\n                'is_dynamic': default_dict['is_dynamic'],\n                'value': default_dict['value']\n            }\n\n    @property\n    def default_value(self):\n        if self.table_ is not None:\n            metadata = self.table_.metadata\n            return get_column_default(\n                self.table_oid,\n                self.column_attnum,\n                self.engine,\n                metadata=metadata,\n            )\n\n    @property\n    def db_type(self):\n        \"\"\"\n        Get this column's database type enum.\n        \"\"\"\n        self._assert_that_engine_is_present()\n        return get_db_type_enum_from_class(self.type.__class__)\n\n    @property\n    def type_options(self):\n        item_type = getattr(self.type, \"item_type\", None)\n        if item_type is not None:\n            item_type_name = get_db_type_enum_from_class(item_type.__class__).id\n        else:\n            item_type_name = None\n        full_type_options = {\n            \"length\": getattr(self.type, \"length\", None),\n            \"precision\": getattr(self.type, \"precision\", None),\n            \"scale\": getattr(self.type, \"scale\", None),\n            \"fields\": getattr(self.type, \"fields\", None),\n            \"item_type\": item_type_name,\n            \"dimensions\": getattr(self.type, \"dimensions\", None)\n        }\n        _type_options = {k: v for k, v in full_type_options.items() if v is not None}\n        return _type_options if _type_options else None\n\n    def _assert_that_engine_is_present(self):\n        if self.engine is None:\n            raise Exception(\"Engine should not be None.\")\n", "path": "db/columns/base.py"}]}