|
| 1 | +from __future__ import annotations |
| 2 | + |
1 | 3 | import time |
2 | | -from typing import Dict, Tuple, List, Optional, Any, Union, Sequence, BinaryIO |
| 4 | +from typing import ( |
| 5 | + Dict, |
| 6 | + Tuple, |
| 7 | + List, |
| 8 | + Optional, |
| 9 | + Any, |
| 10 | + Union, |
| 11 | + Sequence, |
| 12 | + BinaryIO, |
| 13 | + TYPE_CHECKING, |
| 14 | +) |
3 | 15 | import pandas |
4 | 16 |
|
5 | 17 | try: |
|
25 | 37 | DatabaseError, |
26 | 38 | ) |
27 | 39 |
|
28 | | -from databricks.sql.thrift_api.TCLIService import ttypes |
29 | | -from databricks.sql.backend.thrift_backend import ThriftDatabricksClient |
30 | 40 | from databricks.sql.backend.databricks_client import DatabricksClient |
31 | 41 | from databricks.sql.utils import ( |
32 | 42 | ParamEscaper, |
|
49 | 59 | ParameterApproach, |
50 | 60 | ) |
51 | 61 |
|
52 | | -from databricks.sql.result_set import ResultSet, ThriftResultSet |
| 62 | +from databricks.sql.result_set import ResultSet |
53 | 63 | from databricks.sql.types import Row, SSLOptions |
54 | 64 | from databricks.sql.auth.auth import get_python_sql_connector_auth_provider |
55 | 65 | from databricks.sql.experimental.oauth_persistence import OAuthPersistence |
|
60 | 70 | from databricks.sql.common.unified_http_client import UnifiedHttpClient |
61 | 71 | from databricks.sql.common.http import HttpMethod |
62 | 72 |
|
63 | | -from databricks.sql.thrift_api.TCLIService.ttypes import ( |
64 | | - TOpenSessionResp, |
65 | | - TSparkParameter, |
66 | | - TOperationState, |
67 | | -) |
| 73 | +if TYPE_CHECKING: |
| 74 | + # Type-annotation-only imports (deferred by ``from __future__ import |
| 75 | + # annotations``). ``get_protocol_version`` and ``_prepare_native_parameters`` |
| 76 | + # are typed with these Thrift-generated types, but the Thrift backend and |
| 77 | + # its result set are imported lazily (only on the Thrift connect path), so |
| 78 | + # importing this module -- and connecting with the SEA or kernel backend -- |
| 79 | + # never imports the Apache Thrift ``thrift`` package. See |
| 80 | + # ``test_lazy_thrift_import``. |
| 81 | + from databricks.sql.thrift_api.TCLIService.ttypes import ( |
| 82 | + TOpenSessionResp, |
| 83 | + TSparkParameter, |
| 84 | + ) |
68 | 85 | from databricks.sql.telemetry.telemetry_client import ( |
69 | 86 | TelemetryHelper, |
70 | 87 | TelemetryClientFactory, |
|
95 | 112 | TRANSACTION_ISOLATION_LEVEL_REPEATABLE_READ = "REPEATABLE_READ" |
96 | 113 |
|
97 | 114 |
|
| 115 | +def __getattr__(name: str) -> Any: |
| 116 | + """Lazily resolve the Thrift backend class as a module attribute. |
| 117 | +
|
| 118 | + ``client.py`` itself never instantiates ``ThriftDatabricksClient`` (the |
| 119 | + backend is chosen in ``Session.open``), but the name is exposed here as a |
| 120 | + module attribute so it can be resolved without importing the Apache Thrift |
| 121 | + ``thrift`` package at module load -- which is what keeps the SEA/kernel |
| 122 | + connect path Thrift-free (see ``test_lazy_thrift_import``). It also |
| 123 | + preserves the long-standing test seam |
| 124 | + ``patch("databricks.sql.client.ThriftDatabricksClient")``. |
| 125 | + """ |
| 126 | + if name == "ThriftDatabricksClient": |
| 127 | + from databricks.sql.backend.thrift_backend import ThriftDatabricksClient |
| 128 | + |
| 129 | + return ThriftDatabricksClient |
| 130 | + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
| 131 | + |
| 132 | + |
98 | 133 | class Connection: |
99 | 134 | def __init__( |
100 | 135 | self, |
|
0 commit comments