.run_until_complete\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m 95\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m f\u001b[38;5;241m.\u001b[39mdone():\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[1;32m 97\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mEvent loop stopped before Future completed.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m---> 98\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresult\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.11/asyncio/futures.py:203\u001b[0m, in \u001b[0;36mFuture.result\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__log_traceback \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 202\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 203\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception\u001b[38;5;241m.\u001b[39mwith_traceback(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception_tb)\n\u001b[1;32m 204\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_result\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.11/asyncio/tasks.py:277\u001b[0m, in \u001b[0;36mTask.__step\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m 273\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 274\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m exc \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 275\u001b[0m \u001b[38;5;66;03m# We use the `send` method directly, because coroutines\u001b[39;00m\n\u001b[1;32m 276\u001b[0m \u001b[38;5;66;03m# don't have `__iter__` and `__next__` methods.\u001b[39;00m\n\u001b[0;32m--> 277\u001b[0m result \u001b[38;5;241m=\u001b[39m coro\u001b[38;5;241m.\u001b[39msend(\u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 278\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 279\u001b[0m result \u001b[38;5;241m=\u001b[39m coro\u001b[38;5;241m.\u001b[39mthrow(exc)\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.11/site-packages/pyegeria/_client.py:480\u001b[0m, in \u001b[0;36mClient._async_make_request\u001b[0;34m(self, request_type, endpoint, payload, time_out)\u001b[0m\n\u001b[1;32m 478\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m UserNotAuthorizedException(exc_msg)\n\u001b[1;32m 479\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 480\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidParameterException(exc_msg)\n\u001b[1;32m 482\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m response\u001b[38;5;241m.\u001b[39mstatus_code \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;241m500\u001b[39m, \u001b[38;5;241m501\u001b[39m, \u001b[38;5;241m502\u001b[39m, \u001b[38;5;241m503\u001b[39m, \u001b[38;5;241m504\u001b[39m):\n\u001b[1;32m 483\u001b[0m \u001b[38;5;66;03m# server errors\u001b[39;00m\n\u001b[1;32m 484\u001b[0m msg \u001b[38;5;241m=\u001b[39m OMAGCommonErrorCode\u001b[38;5;241m.\u001b[39mEXCEPTION_RESPONSE_FROM_API\u001b[38;5;241m.\u001b[39mvalue[\n\u001b[1;32m 485\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessage_template\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 486\u001b[0m ]\u001b[38;5;241m.\u001b[39mformat(\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 490\u001b[0m OMAGCommonErrorCode\u001b[38;5;241m.\u001b[39mEXCEPTION_RESPONSE_FROM_API\u001b[38;5;241m.\u001b[39mvalue[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessage_id\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[1;32m 491\u001b[0m ) \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m==>System reports:\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m response\u001b[38;5;241m.\u001b[39mreason_phrase \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m\n",
+ "\u001b[0;31mInvalidParameterException\u001b[0m: A client-side error 400 was received by method __step from API call Client during the call https://host.docker.internal:9443/servers/active-metadata-store/open-metadata/framework-services/asset-owner/open-metadata-store/users/garygeeke/metadata-elements/by-search-string?startFrom=start_from&pageSize=page_size. The error message was CLIENT-SIDE-REST-API-CONNECTOR-503-002"
+ ]
+ }
+ ],
+ "source": [
+ "p = LoadedResources(\"active-metadata-store\",\"https://host.docker.internal:9443\", \"garygeeke\", \"secret\")\n",
+ "token = p.create_egeria_bearer_token()\n",
+ "p.get_all_templates()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cd0e31a0-b190-46ba-be20-f647e686d6b7",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/workspaces/Untitled.ipynb b/workspaces/Untitled.ipynb
new file mode 100644
index 0000000..5e9f891
--- /dev/null
+++ b/workspaces/Untitled.ipynb
@@ -0,0 +1,97 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2094e0fc-29c6-4f33-b40e-e67d4f046a5f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyegeria import AutomatedCuration"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5114abc1-ef5f-49a5-a097-745b82b6cf45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import asyncio\n",
+ "import nest_asyncio\n",
+ "nest_asyncio.apply()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "1cb9b8e5-2672-4ae1-a8a3-7ef368ef368c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "client = AutomatedCuration('view-server','https://host.docker.internal:9443','erinoverview','secret')\n",
+ "token = client.create_egeria_bearer_token() "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "458d6da3-bfb8-4f4c-80eb-84f28505d910",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "client = client.get_engine_actions()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "0b614b04-fe66-4f85-b027-57625a0c9127",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'No elements'"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "client"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3fffc1c3-ee0a-4b4f-8bf1-b3b67cc41158",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/workspaces/experiments.ipynb b/workspaces/experiments.ipynb
new file mode 100644
index 0000000..ce91dcc
--- /dev/null
+++ b/workspaces/experiments.ipynb
@@ -0,0 +1,734 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9968014f-4cd4-40fb-959a-13689f5ac01e",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-07-18T00:23:20.558488Z",
+ "start_time": "2024-07-18T00:23:20.551811Z"
+ },
+ "editable": true,
+ "slideshow": {
+ "slide_type": ""
+ },
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import asyncio\n",
+ "import nest_asyncio\n",
+ "nest_asyncio.apply()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "a11585d4-48e0-43c8-aba9-0bbc1b1cbbc1",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-07-18T00:23:22.658459Z",
+ "start_time": "2024-07-18T00:23:22.484398Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "from pyegeria import Platform\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "271affe2-3f66-46cf-b3ec-75fe4e3d2cfe",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-07-18T00:23:24.245215Z",
+ "start_time": "2024-07-18T00:23:24.202681Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'Egeria OMAG Server Platform (version 5.1-SNAPSHOT)\\n'"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p_client = Platform('active-metadata-store', \"https://host.docker.internal:9443\",\"garygeeke\")\n",
+ "p_client.get_platform_origin() "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "802fe1f8-9bd5-4378-ae46-2a677a8466b7",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-07-18T00:27:13.308981Z",
+ "start_time": "2024-07-18T00:27:10.147943Z"
+ },
+ "editable": true,
+ "slideshow": {
+ "slide_type": ""
+ },
+ "tags": []
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n"
+ ],
+ "text/plain": []
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_transports/default.py:69 in │\n",
+ "│ map_httpcore_exceptions │\n",
+ "│ │\n",
+ "│ 66 @contextlib.contextmanager │\n",
+ "│ 67 def map_httpcore_exceptions() -> typing.Iterator[None]: │\n",
+ "│ 68 │ try: │\n",
+ "│ ❱ 69 │ │ yield │\n",
+ "│ 70 │ except Exception as exc: │\n",
+ "│ 71 │ │ mapped_exc = None │\n",
+ "│ 72 │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_transports/default.py:233 in handle_request │\n",
+ "│ │\n",
+ "│ 230 │ │ │ extensions=request.extensions, │\n",
+ "│ 231 │ │ ) │\n",
+ "│ 232 │ │ with map_httpcore_exceptions(): │\n",
+ "│ ❱ 233 │ │ │ resp = self._pool.handle_request(req) │\n",
+ "│ 234 │ │ │\n",
+ "│ 235 │ │ assert isinstance(resp.stream, typing.Iterable) │\n",
+ "│ 236 │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_sync/connection_pool.py:216 in handle_request │\n",
+ "│ │\n",
+ "│ 213 │ │ │ │ closing = self._assign_requests_to_connections() │\n",
+ "│ 214 │ │ │ │\n",
+ "│ 215 │ │ │ self._close_connections(closing) │\n",
+ "│ ❱ 216 │ │ │ raise exc from None │\n",
+ "│ 217 │ │ │\n",
+ "│ 218 │ │ # Return the response. Note that in this case we still have to manage │\n",
+ "│ 219 │ │ # the point at which the response is closed. │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_sync/connection_pool.py:196 in handle_request │\n",
+ "│ │\n",
+ "│ 193 │ │ │ │ │\n",
+ "│ 194 │ │ │ │ try: │\n",
+ "│ 195 │ │ │ │ │ # Send the request on the assigned connection. │\n",
+ "│ ❱ 196 │ │ │ │ │ response = connection.handle_request( │\n",
+ "│ 197 │ │ │ │ │ │ pool_request.request │\n",
+ "│ 198 │ │ │ │ │ ) │\n",
+ "│ 199 │ │ │ │ except ConnectionNotAvailable: │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_sync/connection.py:99 in handle_request │\n",
+ "│ │\n",
+ "│ 96 │ │ │ │ │ │ ) │\n",
+ "│ 97 │ │ except BaseException as exc: │\n",
+ "│ 98 │ │ │ self._connect_failed = True │\n",
+ "│ ❱ 99 │ │ │ raise exc │\n",
+ "│ 100 │ │ │\n",
+ "│ 101 │ │ return self._connection.handle_request(request) │\n",
+ "│ 102 │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_sync/connection.py:76 in handle_request │\n",
+ "│ │\n",
+ "│ 73 │ │ try: │\n",
+ "│ 74 │ │ │ with self._request_lock: │\n",
+ "│ 75 │ │ │ │ if self._connection is None: │\n",
+ "│ ❱ 76 │ │ │ │ │ stream = self._connect(request) │\n",
+ "│ 77 │ │ │ │ │ │\n",
+ "│ 78 │ │ │ │ │ ssl_object = stream.get_extra_info(\"ssl_object\") │\n",
+ "│ 79 │ │ │ │ │ http2_negotiated = ( │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_sync/connection.py:122 in _connect │\n",
+ "│ │\n",
+ "│ 119 │ │ │ │ │ │ \"socket_options\": self._socket_options, │\n",
+ "│ 120 │ │ │ │ │ } │\n",
+ "│ 121 │ │ │ │ │ with Trace(\"connect_tcp\", logger, request, kwargs) as trace: │\n",
+ "│ ❱ 122 │ │ │ │ │ │ stream = self._network_backend.connect_tcp(**kwargs) │\n",
+ "│ 123 │ │ │ │ │ │ trace.return_value = stream │\n",
+ "│ 124 │ │ │ │ else: │\n",
+ "│ 125 │ │ │ │ │ kwargs = { │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_backends/sync.py:205 in connect_tcp │\n",
+ "│ │\n",
+ "│ 202 │ │ │ OSError: ConnectError, │\n",
+ "│ 203 │ │ } │\n",
+ "│ 204 │ │ │\n",
+ "│ ❱ 205 │ │ with map_exceptions(exc_map): │\n",
+ "│ 206 │ │ │ sock = socket.create_connection( │\n",
+ "│ 207 │ │ │ │ address, │\n",
+ "│ 208 │ │ │ │ timeout, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/contextlib.py:158 in __exit__ │\n",
+ "│ │\n",
+ "│ 155 │ │ │ │ # tell if we get the same exception back │\n",
+ "│ 156 │ │ │ │ value = typ() │\n",
+ "│ 157 │ │ │ try: │\n",
+ "│ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │\n",
+ "│ 159 │ │ │ except StopIteration as exc: │\n",
+ "│ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │\n",
+ "│ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in map_exceptions │\n",
+ "│ │\n",
+ "│ 11 │ except Exception as exc: # noqa: PIE786 │\n",
+ "│ 12 │ │ for from_exc, to_exc in map.items(): │\n",
+ "│ 13 │ │ │ if isinstance(exc, from_exc): │\n",
+ "│ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │\n",
+ "│ 15 │ │ raise # pragma: nocover │\n",
+ "│ 16 │\n",
+ "│ 17 │\n",
+ "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
+ "ConnectError: [Errno 111] Connection refused\n",
+ "\n",
+ "The above exception was the direct cause of the following exception:\n",
+ "\n",
+ "╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:951 in _request │\n",
+ "│ │\n",
+ "│ 948 │ │ log.debug(\"Sending HTTP Request: %s %s\", request.method, request.url) │\n",
+ "│ 949 │ │ │\n",
+ "│ 950 │ │ try: │\n",
+ "│ ❱ 951 │ │ │ response = self._client.send( │\n",
+ "│ 952 │ │ │ │ request, │\n",
+ "│ 953 │ │ │ │ stream=stream or self._should_stream_response_body(request=request), │\n",
+ "│ 954 │ │ │ │ **kwargs, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_client.py:914 in send │\n",
+ "│ │\n",
+ "│ 911 │ │ │\n",
+ "│ 912 │ │ auth = self._build_request_auth(request, auth) │\n",
+ "│ 913 │ │ │\n",
+ "│ ❱ 914 │ │ response = self._send_handling_auth( │\n",
+ "│ 915 │ │ │ request, │\n",
+ "│ 916 │ │ │ auth=auth, │\n",
+ "│ 917 │ │ │ follow_redirects=follow_redirects, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_client.py:942 in _send_handling_auth │\n",
+ "│ │\n",
+ "│ 939 │ │ │ request = next(auth_flow) │\n",
+ "│ 940 │ │ │ │\n",
+ "│ 941 │ │ │ while True: │\n",
+ "│ ❱ 942 │ │ │ │ response = self._send_handling_redirects( │\n",
+ "│ 943 │ │ │ │ │ request, │\n",
+ "│ 944 │ │ │ │ │ follow_redirects=follow_redirects, │\n",
+ "│ 945 │ │ │ │ │ history=history, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_client.py:979 in _send_handling_redirects │\n",
+ "│ │\n",
+ "│ 976 │ │ │ for hook in self._event_hooks[\"request\"]: │\n",
+ "│ 977 │ │ │ │ hook(request) │\n",
+ "│ 978 │ │ │ │\n",
+ "│ ❱ 979 │ │ │ response = self._send_single_request(request) │\n",
+ "│ 980 │ │ │ try: │\n",
+ "│ 981 │ │ │ │ for hook in self._event_hooks[\"response\"]: │\n",
+ "│ 982 │ │ │ │ │ hook(response) │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_client.py:1015 in _send_single_request │\n",
+ "│ │\n",
+ "│ 1012 │ │ │ ) │\n",
+ "│ 1013 │ │ │\n",
+ "│ 1014 │ │ with request_context(request=request): │\n",
+ "│ ❱ 1015 │ │ │ response = transport.handle_request(request) │\n",
+ "│ 1016 │ │ │\n",
+ "│ 1017 │ │ assert isinstance(response.stream, SyncByteStream) │\n",
+ "│ 1018 │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_transports/default.py:232 in handle_request │\n",
+ "│ │\n",
+ "│ 229 │ │ │ content=request.stream, │\n",
+ "│ 230 │ │ │ extensions=request.extensions, │\n",
+ "│ 231 │ │ ) │\n",
+ "│ ❱ 232 │ │ with map_httpcore_exceptions(): │\n",
+ "│ 233 │ │ │ resp = self._pool.handle_request(req) │\n",
+ "│ 234 │ │ │\n",
+ "│ 235 │ │ assert isinstance(resp.stream, typing.Iterable) │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/contextlib.py:158 in __exit__ │\n",
+ "│ │\n",
+ "│ 155 │ │ │ │ # tell if we get the same exception back │\n",
+ "│ 156 │ │ │ │ value = typ() │\n",
+ "│ 157 │ │ │ try: │\n",
+ "│ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │\n",
+ "│ 159 │ │ │ except StopIteration as exc: │\n",
+ "│ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │\n",
+ "│ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/httpx/_transports/default.py:86 in │\n",
+ "│ map_httpcore_exceptions │\n",
+ "│ │\n",
+ "│ 83 │ │ │ raise │\n",
+ "│ 84 │ │ │\n",
+ "│ 85 │ │ message = str(exc) │\n",
+ "│ ❱ 86 │ │ raise mapped_exc(message) from exc │\n",
+ "│ 87 │\n",
+ "│ 88 │\n",
+ "│ 89 HTTPCORE_EXC_MAP = { │\n",
+ "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
+ "ConnectError: [Errno 111] Connection refused\n",
+ "\n",
+ "The above exception was the direct cause of the following exception:\n",
+ "\n",
+ "╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
+ "│ /home/jovyan/workspaces/uc_oss_catalog_viewer.py:147 in display_catalog │\n",
+ "│ │\n",
+ "│ 144 │ try: │\n",
+ "│ 145 │ │ console = Console(width=200) │\n",
+ "│ 146 │ │ with console.pager(): │\n",
+ "│ ❱ 147 │ │ │ console.print(generate_table()) │\n",
+ "│ 148 │ │\n",
+ "│ 149 │ except Exception as e: │\n",
+ "│ 150 │ │ print() │\n",
+ "│ │\n",
+ "│ /home/jovyan/workspaces/uc_oss_catalog_viewer.py:49 in generate_table │\n",
+ "│ │\n",
+ "│ 46 │ │ table.add_column(\"Vol/Tab\") │\n",
+ "│ 47 │ │ table.add_column(\"Details\") │\n",
+ "│ 48 │ │ │\n",
+ "│ ❱ 49 │ │ c_list = uc_client.catalogs.list() │\n",
+ "│ 50 │ │ catalogs= c_list.catalogs │\n",
+ "│ 51 │ │ for catalog in catalogs: │\n",
+ "│ 52 │ │ │ # cat_info = catalog.CatalogInfo │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/resources/catalogs.py:211 in list │\n",
+ "│ │\n",
+ "│ 208 │ │ │\n",
+ "│ 209 │ │ timeout: Override the client-level default timeout for this request, in second │\n",
+ "│ 210 │ │ \"\"\" │\n",
+ "│ ❱ 211 │ │ return self._get( │\n",
+ "│ 212 │ │ │ \"/catalogs\", │\n",
+ "│ 213 │ │ │ options=make_request_options( │\n",
+ "│ 214 │ │ │ │ extra_headers=extra_headers, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:1168 in get │\n",
+ "│ │\n",
+ "│ 1165 │ │ opts = FinalRequestOptions.construct(method=\"get\", url=path, **options) │\n",
+ "│ 1166 │ │ # cast is required because mypy complains about returning Any even though │\n",
+ "│ 1167 │ │ # it understands the type variables │\n",
+ "│ ❱ 1168 │ │ return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=str │\n",
+ "│ 1169 │ │\n",
+ "│ 1170 │ @overload │\n",
+ "│ 1171 │ def post( │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:920 in request │\n",
+ "│ │\n",
+ "│ 917 │ │ stream: bool = False, │\n",
+ "│ 918 │ │ stream_cls: type[_StreamT] | None = None, │\n",
+ "│ 919 │ ) -> ResponseT | _StreamT: │\n",
+ "│ ❱ 920 │ │ return self._request( │\n",
+ "│ 921 │ │ │ cast_to=cast_to, │\n",
+ "│ 922 │ │ │ options=options, │\n",
+ "│ 923 │ │ │ stream=stream, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:975 in _request │\n",
+ "│ │\n",
+ "│ 972 │ │ │ log.debug(\"Encountered Exception\", exc_info=True) │\n",
+ "│ 973 │ │ │ │\n",
+ "│ 974 │ │ │ if retries > 0: │\n",
+ "│ ❱ 975 │ │ │ │ return self._retry_request( │\n",
+ "│ 976 │ │ │ │ │ options, │\n",
+ "│ 977 │ │ │ │ │ cast_to, │\n",
+ "│ 978 │ │ │ │ │ retries, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:1051 in _retry_request │\n",
+ "│ │\n",
+ "│ 1048 │ │ # different thread if necessary. │\n",
+ "│ 1049 │ │ time.sleep(timeout) │\n",
+ "│ 1050 │ │ │\n",
+ "│ ❱ 1051 │ │ return self._request( │\n",
+ "│ 1052 │ │ │ options=options, │\n",
+ "│ 1053 │ │ │ cast_to=cast_to, │\n",
+ "│ 1054 │ │ │ remaining_retries=remaining, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:975 in _request │\n",
+ "│ │\n",
+ "│ 972 │ │ │ log.debug(\"Encountered Exception\", exc_info=True) │\n",
+ "│ 973 │ │ │ │\n",
+ "│ 974 │ │ │ if retries > 0: │\n",
+ "│ ❱ 975 │ │ │ │ return self._retry_request( │\n",
+ "│ 976 │ │ │ │ │ options, │\n",
+ "│ 977 │ │ │ │ │ cast_to, │\n",
+ "│ 978 │ │ │ │ │ retries, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:1051 in _retry_request │\n",
+ "│ │\n",
+ "│ 1048 │ │ # different thread if necessary. │\n",
+ "│ 1049 │ │ time.sleep(timeout) │\n",
+ "│ 1050 │ │ │\n",
+ "│ ❱ 1051 │ │ return self._request( │\n",
+ "│ 1052 │ │ │ options=options, │\n",
+ "│ 1053 │ │ │ cast_to=cast_to, │\n",
+ "│ 1054 │ │ │ remaining_retries=remaining, │\n",
+ "│ │\n",
+ "│ /opt/conda/lib/python3.11/site-packages/unitycatalog/_base_client.py:985 in _request │\n",
+ "│ │\n",
+ "│ 982 │ │ │ │ ) │\n",
+ "│ 983 │ │ │ │\n",
+ "│ 984 │ │ │ log.debug(\"Raising connection error\") │\n",
+ "│ ❱ 985 │ │ │ raise APIConnectionError(request=request) from err │\n",
+ "│ 986 │ │ │\n",
+ "│ 987 │ │ log.debug( │\n",
+ "│ 988 │ │ │ 'HTTP Response: %s %s \"%i %s\" %s', │\n",
+ "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
+ "APIConnectionError: Connection error.\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/_transports/\u001b[0m\u001b[1;33mdefault.py\u001b[0m:\u001b[94m69\u001b[0m in \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[92mmap_httpcore_exceptions\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 66 \u001b[0m\u001b[1;95m@contextlib\u001b[0m.contextmanager \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 67 \u001b[0m\u001b[94mdef\u001b[0m \u001b[92mmap_httpcore_exceptions\u001b[0m() -> typing.Iterator[\u001b[94mNone\u001b[0m]: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 68 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 69 \u001b[2m│ │ \u001b[0m\u001b[94myield\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 70 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mException\u001b[0m \u001b[94mas\u001b[0m exc: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 71 \u001b[0m\u001b[2m│ │ \u001b[0mmapped_exc = \u001b[94mNone\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 72 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/_transports/\u001b[0m\u001b[1;33mdefault.py\u001b[0m:\u001b[94m233\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m230 \u001b[0m\u001b[2m│ │ │ \u001b[0mextensions=request.extensions, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m231 \u001b[0m\u001b[2m│ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m232 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mwith\u001b[0m map_httpcore_exceptions(): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m233 \u001b[2m│ │ │ \u001b[0mresp = \u001b[96mself\u001b[0m._pool.handle_request(req) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m234 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m235 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94massert\u001b[0m \u001b[96misinstance\u001b[0m(resp.stream, typing.Iterable) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m236 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_sync/\u001b[0m\u001b[1;33mconnection_pool.py\u001b[0m:\u001b[94m216\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m213 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mclosing = \u001b[96mself\u001b[0m._assign_requests_to_connections() \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m214 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m215 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m._close_connections(closing) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m216 \u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m exc \u001b[94mfrom\u001b[0m \u001b[94mNone\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m217 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m218 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Return the response. Note that in this case we still have to manage\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m219 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# the point at which the response is closed.\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_sync/\u001b[0m\u001b[1;33mconnection_pool.py\u001b[0m:\u001b[94m196\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m193 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m194 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m195 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m\u001b[2m# Send the request on the assigned connection.\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m196 \u001b[2m│ │ │ │ │ \u001b[0mresponse = connection.handle_request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m197 \u001b[0m\u001b[2m│ │ │ │ │ │ \u001b[0mpool_request.request \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m198 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m199 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mexcept\u001b[0m ConnectionNotAvailable: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_sync/\u001b[0m\u001b[1;33mconnection.py\u001b[0m:\u001b[94m99\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 96 \u001b[0m\u001b[2m│ │ │ │ │ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 97 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mBaseException\u001b[0m \u001b[94mas\u001b[0m exc: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 98 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m._connect_failed = \u001b[94mTrue\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 99 \u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m exc \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m100 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m101 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._connection.handle_request(request) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m102 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_sync/\u001b[0m\u001b[1;33mconnection.py\u001b[0m:\u001b[94m76\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 73 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 74 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m \u001b[96mself\u001b[0m._request_lock: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 75 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mself\u001b[0m._connection \u001b[95mis\u001b[0m \u001b[94mNone\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 76 \u001b[2m│ │ │ │ │ \u001b[0mstream = \u001b[96mself\u001b[0m._connect(request) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 77 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 78 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mssl_object = stream.get_extra_info(\u001b[33m\"\u001b[0m\u001b[33mssl_object\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 79 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mhttp2_negotiated = ( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_sync/\u001b[0m\u001b[1;33mconnection.py\u001b[0m:\u001b[94m122\u001b[0m in \u001b[92m_connect\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m119 \u001b[0m\u001b[2m│ │ │ │ │ │ \u001b[0m\u001b[33m\"\u001b[0m\u001b[33msocket_options\u001b[0m\u001b[33m\"\u001b[0m: \u001b[96mself\u001b[0m._socket_options, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m120 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m} \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m121 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m\u001b[94mwith\u001b[0m Trace(\u001b[33m\"\u001b[0m\u001b[33mconnect_tcp\u001b[0m\u001b[33m\"\u001b[0m, logger, request, kwargs) \u001b[94mas\u001b[0m trace: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m122 \u001b[2m│ │ │ │ │ │ \u001b[0mstream = \u001b[96mself\u001b[0m._network_backend.connect_tcp(**kwargs) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m123 \u001b[0m\u001b[2m│ │ │ │ │ │ \u001b[0mtrace.return_value = stream \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m124 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m125 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mkwargs = { \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/_backends/\u001b[0m\u001b[1;33msync.py\u001b[0m:\u001b[94m205\u001b[0m in \u001b[92mconnect_tcp\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m202 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mOSError\u001b[0m: ConnectError, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m203 \u001b[0m\u001b[2m│ │ \u001b[0m} \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m204 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m205 \u001b[2m│ │ \u001b[0m\u001b[94mwith\u001b[0m map_exceptions(exc_map): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m206 \u001b[0m\u001b[2m│ │ │ \u001b[0msock = socket.create_connection( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m207 \u001b[0m\u001b[2m│ │ │ │ \u001b[0maddress, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m208 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mtimeout, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/\u001b[0m\u001b[1;33mcontextlib.py\u001b[0m:\u001b[94m158\u001b[0m in \u001b[92m__exit__\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m155 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# tell if we get the same exception back\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m156 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mvalue = typ() \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m157 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m158 \u001b[2m│ │ │ │ \u001b[0m\u001b[96mself\u001b[0m.gen.throw(typ, value, traceback) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m159 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mStopIteration\u001b[0m \u001b[94mas\u001b[0m exc: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m160 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# Suppress StopIteration *unless* it's the same exception that\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m161 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# was passed to throw(). This prevents a StopIteration\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpcore/\u001b[0m\u001b[1;33m_exceptions.py\u001b[0m:\u001b[94m14\u001b[0m in \u001b[92mmap_exceptions\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m11 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mException\u001b[0m \u001b[94mas\u001b[0m exc: \u001b[2m# noqa: PIE786\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m12 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mfor\u001b[0m from_exc, to_exc \u001b[95min\u001b[0m \u001b[96mmap\u001b[0m.items(): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m13 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96misinstance\u001b[0m(exc, from_exc): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m14 \u001b[2m│ │ │ │ \u001b[0m\u001b[94mraise\u001b[0m to_exc(exc) \u001b[94mfrom\u001b[0m \u001b[4;96mexc\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m15 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mraise\u001b[0m \u001b[2m# pragma: nocover\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m16 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m17 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n",
+ "\u001b[1;91mConnectError: \u001b[0m\u001b[1m[\u001b[0mErrno \u001b[1;36m111\u001b[0m\u001b[1m]\u001b[0m Connection refused\n",
+ "\n",
+ "\u001b[3mThe above exception was the direct cause of the following exception:\u001b[0m\n",
+ "\n",
+ "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m951\u001b[0m in \u001b[92m_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 948 \u001b[0m\u001b[2m│ │ \u001b[0mlog.debug(\u001b[33m\"\u001b[0m\u001b[33mSending HTTP Request: \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m\"\u001b[0m, request.method, request.url) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 949 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 950 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 951 \u001b[2m│ │ │ \u001b[0mresponse = \u001b[96mself\u001b[0m._client.send( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 952 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mrequest, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 953 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mstream=stream \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._should_stream_response_body(request=request), \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 954 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m**kwargs, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/\u001b[0m\u001b[1;33m_client.py\u001b[0m:\u001b[94m914\u001b[0m in \u001b[92msend\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 911 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 912 \u001b[0m\u001b[2m│ │ \u001b[0mauth = \u001b[96mself\u001b[0m._build_request_auth(request, auth) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 913 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 914 \u001b[2m│ │ \u001b[0mresponse = \u001b[96mself\u001b[0m._send_handling_auth( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 915 \u001b[0m\u001b[2m│ │ │ \u001b[0mrequest, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 916 \u001b[0m\u001b[2m│ │ │ \u001b[0mauth=auth, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 917 \u001b[0m\u001b[2m│ │ │ \u001b[0mfollow_redirects=follow_redirects, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/\u001b[0m\u001b[1;33m_client.py\u001b[0m:\u001b[94m942\u001b[0m in \u001b[92m_send_handling_auth\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 939 \u001b[0m\u001b[2m│ │ │ \u001b[0mrequest = \u001b[96mnext\u001b[0m(auth_flow) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 940 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 941 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwhile\u001b[0m \u001b[94mTrue\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 942 \u001b[2m│ │ │ │ \u001b[0mresponse = \u001b[96mself\u001b[0m._send_handling_redirects( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 943 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mrequest, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 944 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mfollow_redirects=follow_redirects, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 945 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mhistory=history, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/\u001b[0m\u001b[1;33m_client.py\u001b[0m:\u001b[94m979\u001b[0m in \u001b[92m_send_handling_redirects\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 976 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mfor\u001b[0m hook \u001b[95min\u001b[0m \u001b[96mself\u001b[0m._event_hooks[\u001b[33m\"\u001b[0m\u001b[33mrequest\u001b[0m\u001b[33m\"\u001b[0m]: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 977 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mhook(request) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 978 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 979 \u001b[2m│ │ │ \u001b[0mresponse = \u001b[96mself\u001b[0m._send_single_request(request) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 980 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 981 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mfor\u001b[0m hook \u001b[95min\u001b[0m \u001b[96mself\u001b[0m._event_hooks[\u001b[33m\"\u001b[0m\u001b[33mresponse\u001b[0m\u001b[33m\"\u001b[0m]: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 982 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mhook(response) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/\u001b[0m\u001b[1;33m_client.py\u001b[0m:\u001b[94m1015\u001b[0m in \u001b[92m_send_single_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1012 \u001b[0m\u001b[2m│ │ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1013 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1014 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mwith\u001b[0m request_context(request=request): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1015 \u001b[2m│ │ │ \u001b[0mresponse = transport.handle_request(request) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1016 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1017 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94massert\u001b[0m \u001b[96misinstance\u001b[0m(response.stream, SyncByteStream) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1018 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/_transports/\u001b[0m\u001b[1;33mdefault.py\u001b[0m:\u001b[94m232\u001b[0m in \u001b[92mhandle_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m229 \u001b[0m\u001b[2m│ │ │ \u001b[0mcontent=request.stream, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m230 \u001b[0m\u001b[2m│ │ │ \u001b[0mextensions=request.extensions, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m231 \u001b[0m\u001b[2m│ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m232 \u001b[2m│ │ \u001b[0m\u001b[94mwith\u001b[0m map_httpcore_exceptions(): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m233 \u001b[0m\u001b[2m│ │ │ \u001b[0mresp = \u001b[96mself\u001b[0m._pool.handle_request(req) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m234 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m235 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94massert\u001b[0m \u001b[96misinstance\u001b[0m(resp.stream, typing.Iterable) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/\u001b[0m\u001b[1;33mcontextlib.py\u001b[0m:\u001b[94m158\u001b[0m in \u001b[92m__exit__\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m155 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# tell if we get the same exception back\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m156 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mvalue = typ() \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m157 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m158 \u001b[2m│ │ │ │ \u001b[0m\u001b[96mself\u001b[0m.gen.throw(typ, value, traceback) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m159 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mStopIteration\u001b[0m \u001b[94mas\u001b[0m exc: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m160 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# Suppress StopIteration *unless* it's the same exception that\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m161 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# was passed to throw(). This prevents a StopIteration\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/httpx/_transports/\u001b[0m\u001b[1;33mdefault.py\u001b[0m:\u001b[94m86\u001b[0m in \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[92mmap_httpcore_exceptions\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 83 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 84 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 85 \u001b[0m\u001b[2m│ │ \u001b[0mmessage = \u001b[96mstr\u001b[0m(exc) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 86 \u001b[2m│ │ \u001b[0m\u001b[94mraise\u001b[0m mapped_exc(message) \u001b[94mfrom\u001b[0m \u001b[4;96mexc\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 87 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 88 \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 89 \u001b[0mHTTPCORE_EXC_MAP = { \u001b[31m│\u001b[0m\n",
+ "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n",
+ "\u001b[1;91mConnectError: \u001b[0m\u001b[1m[\u001b[0mErrno \u001b[1;36m111\u001b[0m\u001b[1m]\u001b[0m Connection refused\n",
+ "\n",
+ "\u001b[3mThe above exception was the direct cause of the following exception:\u001b[0m\n",
+ "\n",
+ "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/home/jovyan/workspaces/\u001b[0m\u001b[1;33muc_oss_catalog_viewer.py\u001b[0m:\u001b[94m147\u001b[0m in \u001b[92mdisplay_catalog\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m144 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m145 \u001b[0m\u001b[2m│ │ \u001b[0mconsole = Console(width=\u001b[94m200\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m146 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mwith\u001b[0m console.pager(): \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m147 \u001b[2m│ │ │ \u001b[0mconsole.print(generate_table()) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m148 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m149 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mException\u001b[0m \u001b[94mas\u001b[0m e: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m150 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[96mprint\u001b[0m() \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/home/jovyan/workspaces/\u001b[0m\u001b[1;33muc_oss_catalog_viewer.py\u001b[0m:\u001b[94m49\u001b[0m in \u001b[92mgenerate_table\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 46 \u001b[0m\u001b[2m│ │ \u001b[0mtable.add_column(\u001b[33m\"\u001b[0m\u001b[33mVol/Tab\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 47 \u001b[0m\u001b[2m│ │ \u001b[0mtable.add_column(\u001b[33m\"\u001b[0m\u001b[33mDetails\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 48 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 49 \u001b[2m│ │ \u001b[0mc_list = uc_client.catalogs.list() \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 50 \u001b[0m\u001b[2m│ │ \u001b[0mcatalogs= c_list.catalogs \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 51 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mfor\u001b[0m catalog \u001b[95min\u001b[0m catalogs: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 52 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[2m# cat_info = catalog.CatalogInfo\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/resources/\u001b[0m\u001b[1;33mcatalogs.py\u001b[0m:\u001b[94m211\u001b[0m in \u001b[92mlist\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m208 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m209 \u001b[0m\u001b[2;33m│ │ \u001b[0m\u001b[33mtimeout: Override the client-level default timeout for this request, in second\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m210 \u001b[0m\u001b[2;33m│ │ \u001b[0m\u001b[33m\"\"\"\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m211 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._get( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m212 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[33m\"\u001b[0m\u001b[33m/catalogs\u001b[0m\u001b[33m\"\u001b[0m, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m213 \u001b[0m\u001b[2m│ │ │ \u001b[0moptions=make_request_options( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m214 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mextra_headers=extra_headers, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m1168\u001b[0m in \u001b[92mget\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1165 \u001b[0m\u001b[2m│ │ \u001b[0mopts = FinalRequestOptions.construct(method=\u001b[33m\"\u001b[0m\u001b[33mget\u001b[0m\u001b[33m\"\u001b[0m, url=path, **options) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# cast is required because mypy complains about returning Any even though\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1167 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# it understands the type variables\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1168 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m cast(ResponseT, \u001b[96mself\u001b[0m.request(cast_to, opts, stream=stream, stream_cls=str \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1169 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1170 \u001b[0m\u001b[2m│ \u001b[0m\u001b[1;95m@overload\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1171 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mdef\u001b[0m \u001b[92mpost\u001b[0m( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m920\u001b[0m in \u001b[92mrequest\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 917 \u001b[0m\u001b[2m│ │ \u001b[0mstream: \u001b[96mbool\u001b[0m = \u001b[94mFalse\u001b[0m, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 918 \u001b[0m\u001b[2m│ │ \u001b[0mstream_cls: \u001b[96mtype\u001b[0m[_StreamT] | \u001b[94mNone\u001b[0m = \u001b[94mNone\u001b[0m, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 919 \u001b[0m\u001b[2m│ \u001b[0m) -> ResponseT | _StreamT: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 920 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 921 \u001b[0m\u001b[2m│ │ │ \u001b[0mcast_to=cast_to, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 922 \u001b[0m\u001b[2m│ │ │ \u001b[0moptions=options, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 923 \u001b[0m\u001b[2m│ │ │ \u001b[0mstream=stream, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m975\u001b[0m in \u001b[92m_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 972 \u001b[0m\u001b[2m│ │ │ \u001b[0mlog.debug(\u001b[33m\"\u001b[0m\u001b[33mEncountered Exception\u001b[0m\u001b[33m\"\u001b[0m, exc_info=\u001b[94mTrue\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 973 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 974 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m retries > \u001b[94m0\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 975 \u001b[2m│ │ │ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._retry_request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 976 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0moptions, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 977 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mcast_to, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 978 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mretries, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m1051\u001b[0m in \u001b[92m_retry_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1048 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# different thread if necessary.\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1049 \u001b[0m\u001b[2m│ │ \u001b[0mtime.sleep(timeout) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1050 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1051 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1052 \u001b[0m\u001b[2m│ │ │ \u001b[0moptions=options, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1053 \u001b[0m\u001b[2m│ │ │ \u001b[0mcast_to=cast_to, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1054 \u001b[0m\u001b[2m│ │ │ \u001b[0mremaining_retries=remaining, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m975\u001b[0m in \u001b[92m_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 972 \u001b[0m\u001b[2m│ │ │ \u001b[0mlog.debug(\u001b[33m\"\u001b[0m\u001b[33mEncountered Exception\u001b[0m\u001b[33m\"\u001b[0m, exc_info=\u001b[94mTrue\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 973 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 974 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m retries > \u001b[94m0\u001b[0m: \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 975 \u001b[2m│ │ │ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._retry_request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 976 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0moptions, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 977 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mcast_to, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 978 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mretries, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m1051\u001b[0m in \u001b[92m_retry_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1048 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# different thread if necessary.\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1049 \u001b[0m\u001b[2m│ │ \u001b[0mtime.sleep(timeout) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1050 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1051 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m._request( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1052 \u001b[0m\u001b[2m│ │ │ \u001b[0moptions=options, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1053 \u001b[0m\u001b[2m│ │ │ \u001b[0mcast_to=cast_to, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m1054 \u001b[0m\u001b[2m│ │ │ \u001b[0mremaining_retries=remaining, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2;33m/opt/conda/lib/python3.11/site-packages/unitycatalog/\u001b[0m\u001b[1;33m_base_client.py\u001b[0m:\u001b[94m985\u001b[0m in \u001b[92m_request\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 982 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 983 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 984 \u001b[0m\u001b[2m│ │ │ \u001b[0mlog.debug(\u001b[33m\"\u001b[0m\u001b[33mRaising connection error\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 985 \u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m APIConnectionError(request=request) \u001b[94mfrom\u001b[0m \u001b[4;96merr\u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 986 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 987 \u001b[0m\u001b[2m│ │ \u001b[0mlog.debug( \u001b[31m│\u001b[0m\n",
+ "\u001b[31m│\u001b[0m \u001b[2m 988 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[33m'\u001b[0m\u001b[33mHTTP Response: \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m \u001b[0m\u001b[33m\"\u001b[0m\u001b[33m%i\u001b[0m\u001b[33m \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m \u001b[0m\u001b[33m%s\u001b[0m\u001b[33m'\u001b[0m, \u001b[31m│\u001b[0m\n",
+ "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n",
+ "\u001b[1;91mAPIConnectionError: \u001b[0mConnection error.\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%run uc_oss_catalog_viewer.py\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4885e0e1-2a71-420b-b3d3-257e4eb321e3",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/workspaces/starter.jupyterlab-workspace b/workspaces/starter.jupyterlab-workspace
new file mode 100644
index 0000000..3211591
--- /dev/null
+++ b/workspaces/starter.jupyterlab-workspace
@@ -0,0 +1 @@
+{"data":{"layout-restorer:data":{"main":{"dock":{"type":"split-area","orientation":"vertical","sizes":[0.5,0.5],"children":[{"type":"tab-area","currentIndex":1,"widgets":["terminal:1","terminal:2"]},{"type":"tab-area","currentIndex":0,"widgets":["notebook:workspaces/Untitled1.ipynb"]}]},"current":"terminal:2"},"down":{"size":0,"widgets":[]},"left":{"collapsed":false,"visible":true,"current":"filebrowser","widgets":["filebrowser","running-sessions","git-sessions","@jupyterlab/toc:plugin","extensionmanager.main-view"],"widgetStates":{"jp-running-sessions":{"sizes":[0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666],"expansionStates":[false,false,false,false,false,false]},"extensionmanager.main-view":{"sizes":[0.3333333333333333,0.3333333333333333,0.3333333333333333],"expansionStates":[false,false,false]}}},"right":{"collapsed":true,"visible":true,"widgets":["jp-property-inspector","debugger-sidebar"],"widgetStates":{"jp-debugger-sidebar":{"sizes":[0.2,0.2,0.2,0.2,0.2],"expansionStates":[false,false,false,false,false]}}},"relativeSizes":[0.15991077119184194,0.840089228808158,0],"top":{"simpleVisibility":true}},"docmanager:recents":{"opened":[{"path":"workspaces","contentType":"directory","root":"/home/jovyan"},{"path":"workspaces/Untitled1.ipynb","contentType":"notebook","factory":"Notebook","root":"/home/jovyan"}],"closed":[]},"file-browser-filebrowser:cwd":{"path":"workspaces"},"notebook:workspaces/Untitled1.ipynb":{"data":{"path":"workspaces/Untitled1.ipynb","factory":"Notebook"}},"terminal:1":{"data":{"name":"1"}},"terminal:2":{"data":{"name":"2"}}},"metadata":{"id":"starter","last_modified":"2024-07-17T21:18:11.194040+00:00","created":"2024-07-17T21:18:11.194040+00:00"}}
\ No newline at end of file
diff --git a/workspaces/uc_oss_catalog_viewer.py b/workspaces/uc_oss_catalog_viewer.py
new file mode 100644
index 0000000..d61e7e6
--- /dev/null
+++ b/workspaces/uc_oss_catalog_viewer.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python3
+"""
+SPDX-License-Identifier: Apache-2.0
+Copyright Contributors to the ODPi Egeria project.
+
+A simple UC catalog viewer using the RICH textual interface.
+
+
+"""
+import argparse
+import time
+
+from rich import box
+from rich.console import Console
+from rich.markdown import Markdown
+from rich.table import Table
+from rich.text import Text
+from rich.live import Live
+
+
+from unitycatalog import Unitycatalog
+from unitycatalog.types import (catalog_info, catalog_list_response,
+ schema_info, schema_list_response,
+ volume_info, volume_list_response,
+ )
+
+
+def display_catalog(url:str = "http://egeria.pdr-associates.com:8070"):
+ base_url = url + "/api/2.1/unity-catalog"
+ uc_client = Unitycatalog(base_url=base_url)
+
+ def generate_table() -> Table:
+ """Make a new table."""
+ table = Table(
+ title=f"UC OSS Catalog @ {time.asctime()}",
+ header_style="white on dark_blue",
+ show_lines=True,
+ box=box.ROUNDED,
+ caption=f"Running on {url}",
+ expand=True
+ )
+ table.add_column("Catalog Name")
+ table.add_column("Catalog Comment")
+ table.add_column("Schema Name")
+ table.add_column("Schema Comment")
+ table.add_column("Vol/Tab")
+ table.add_column("Details")
+
+ c_list = uc_client.catalogs.list()
+ catalogs= c_list.catalogs
+ for catalog in catalogs:
+ # cat_info = catalog.CatalogInfo
+ cat_name = catalog.name
+ cat_comment = catalog.comment
+
+ s_list = uc_client.schemas.list(catalog_name = cat_name)
+ schemas = s_list.schemas
+ for schema in schemas:
+ schema_name = schema.name
+ schema_comment = schema.comment
+ v_list = uc_client.volumes.list(catalog_name = cat_name, schema_name = schema_name)
+ volumes = v_list.volumes
+ volume_md = " "
+ volumes_m = "Volumes"
+ volume_m = " "
+ tab_list = uc_client.tables.list(catalog_name = cat_name, schema_name = schema_name)
+ tables = tab_list.tables
+ tables_m = "Tables"
+
+ func_list = uc_client.functions.list(catalog_name = cat_name, schema_name = schema_name)
+ functions = func_list.functions
+ if (functions is not None) and (len(functions) > 0):
+ function_m = "Functions"
+ for function in functions:
+ function_name = function.name
+ function_comment = function.comment
+ function_sql = function.sql_data_access
+ function_id = function.function_id
+ function_type = function.full_data_type
+ function_m = (f"{function_m}\n* name: {function_name}\n"
+ f"\t* comment: {function_comment}\n"
+ f"\t* function_id: {function_id}\n"
+ f"\t* function_type: {function_type}\n"
+ f"\t* sql_access: {function_sql}\n")
+ table.add_row(cat_name, cat_comment, schema_name, schema_comment, Text(function_m))
+ if (volumes is not None) and (len(volumes) > 0):
+ for volume in volumes:
+ volume_name = volume.name
+ volume_comment = volume.comment
+ volume_created_at = volume.created_at
+ volume_updated_at = volume.updated_at
+ volume_id = volume.volume_id
+ volume_type = volume.volume_type
+ volume_storage_location = volume.storage_location
+ volume_m = (f"{volume_m}\n* name: {volume_name}\n"
+ f"\t* comment: {volume_comment}\n"
+ f"\t* created_at: {volume_created_at}\n"
+ f"\t* updated_at: {volume_updated_at}\n"
+ f"\t* volume_id: {volume_id}\n"
+ f"\t* volume_type: {volume_type}\n"
+ f"\t* storage_location: {volume_storage_location}\n")
+ volumes_m = f"{volumes_m}\n{volume_m}"
+ table.add_row(cat_name, cat_comment, schema_name, schema_comment, Text(volumes_m))
+ tab_m = " "
+ if (tables is not None) and (len(tables) > 0):
+ for tab in tables:
+ tab_name = tab.name
+ tab_comment = tab.comment
+ tab_created_at = tab.created_at
+
+ tab_src_format = tab.data_source_format
+ tab_id = tab.table_id
+ tab_type = tab.table_type
+ tab_updated_at = tab.updated_at
+ columns = tab.columns
+ col_m = " "
+ col_tab = Table()
+ col_tab.add_column("name")
+ col_tab.add_column("type")
+ col_tab.add_column("nullable")
+ col_tab.add_column("comment")
+
+ for col in columns:
+ col_nullable = "true" if col.nullable else "false"
+ col_tab.add_row(col.name, col.type_text, col_nullable, col.comment)
+
+ table_m = (f"{tab_m}\n* name: {tab_name}\n"
+ f"\t* comment: {tab_comment}\n"
+ f"\t* created_at: {tab_created_at}\n"
+ f"\t* updated_at: {tab_updated_at}\n"
+ f"\t* table_id: {tab_id}\n"
+ f"\t* table_type: {tab_type}\n"
+ f"\t* src_format: {tab_src_format}\n"
+ )
+
+ tables_m = f"{tables_m}\n{table_m}"
+ table.add_row(cat_name, cat_comment, schema_name, schema_comment, Text(tables_m), col_tab)
+ fcn_m = " "
+
+
+
+ return table
+
+ try:
+ console = Console(width=200)
+ with console.pager():
+ console.print(generate_table())
+
+ except Exception as e:
+ print()
+ console.print_exception()
+
+ finally:
+ uc_client.close()
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--server", help="Name of the server to display status for")
+ parser.add_argument("--url", help="URL Platform to connect to")
+ parser.add_argument("--userid", help="User Id")
+ args = parser.parse_args()
+
+ server = args.server if args.server is not None else "engine-host"
+ url = args.url if args.url is not None else "http://localhost:8080"
+ userid = args.userid if args.userid is not None else 'garygeeke'
+ display_catalog(url)