databricks-sql-connector 4.2.2__tar.gz → 4.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/CHANGELOG.md +8 -0
  2. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/PKG-INFO +7 -5
  3. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/pyproject.toml +9 -5
  4. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/__init__.py +1 -1
  5. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/auth_utils.py +0 -17
  6. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/token_federation.py +3 -3
  7. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/utils/http_client.py +4 -2
  8. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/common/feature_flag.py +3 -1
  9. databricks_sql_connector-4.2.4/src/databricks/sql/common/url_utils.py +45 -0
  10. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/telemetry_client.py +4 -3
  11. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/LICENSE +0 -0
  12. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/README.md +0 -0
  13. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/__init__.py +0 -0
  14. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/__init__.py +0 -0
  15. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/auth.py +0 -0
  16. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/authenticators.py +0 -0
  17. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/common.py +0 -0
  18. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/endpoint.py +0 -0
  19. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/oauth.py +0 -0
  20. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/oauth_http_handler.py +0 -0
  21. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/retry.py +0 -0
  22. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/auth/thrift_http_client.py +0 -0
  23. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/databricks_client.py +0 -0
  24. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/backend.py +0 -0
  25. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/models/__init__.py +0 -0
  26. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/models/base.py +0 -0
  27. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/models/requests.py +0 -0
  28. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/models/responses.py +0 -0
  29. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/queue.py +0 -0
  30. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/result_set.py +0 -0
  31. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/utils/constants.py +0 -0
  32. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/utils/conversion.py +0 -0
  33. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/utils/filters.py +0 -0
  34. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/sea/utils/normalize.py +0 -0
  35. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/thrift_backend.py +0 -0
  36. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/types.py +0 -0
  37. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/utils/__init__.py +0 -0
  38. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/backend/utils/guid_utils.py +0 -0
  39. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/client.py +0 -0
  40. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/cloudfetch/download_manager.py +0 -0
  41. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/cloudfetch/downloader.py +0 -0
  42. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/common/http.py +0 -0
  43. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/common/http_utils.py +0 -0
  44. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/common/unified_http_client.py +0 -0
  45. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/exc.py +0 -0
  46. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/experimental/__init__.py +0 -0
  47. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/experimental/oauth_persistence.py +0 -0
  48. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/parameters/__init__.py +0 -0
  49. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/parameters/native.py +0 -0
  50. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/parameters/py.typed +0 -0
  51. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/py.typed +0 -0
  52. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/result_set.py +0 -0
  53. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/session.py +0 -0
  54. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/circuit_breaker_manager.py +0 -0
  55. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/latency_logger.py +0 -0
  56. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/models/endpoint_models.py +0 -0
  57. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/models/enums.py +0 -0
  58. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/models/event.py +0 -0
  59. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/models/frontend_logs.py +0 -0
  60. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/telemetry_push_client.py +0 -0
  61. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/telemetry/utils.py +0 -0
  62. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/TCLIService/TCLIService-remote +0 -0
  63. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/TCLIService/TCLIService.py +0 -0
  64. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/TCLIService/__init__.py +0 -0
  65. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/TCLIService/constants.py +0 -0
  66. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/TCLIService/ttypes.py +0 -0
  67. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/thrift_api/__init__.py +0 -0
  68. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/types.py +0 -0
  69. {databricks_sql_connector-4.2.2 → databricks_sql_connector-4.2.4}/src/databricks/sql/utils.py +0 -0
@@ -1,5 +1,13 @@
1
1
  # Release History
2
2
 
3
+ # 4.2.4 (2026-01-07)
4
+ - Fixed the exception handler close() on _TelemetryClientHolder (databricks/databricks-sql-python#723 by @msrathore-db)
5
+ - Created util method to normalise http protocol in http path (databricks/databricks-sql-python#724 by @nikhilsuri-db)
6
+
7
+ # 4.2.3 (2025-12-18)
8
+ - added pandas < 2.4.0 support and tests for py 3.14 (databricks/databricks-sql-python#720 by @sreekanth-db)
9
+ - pandas 2.3.3 support for py < 3.14 (databricks/databricks-sql-python#721 by @sreekanth-db)
10
+
3
11
  # 4.2.2 (2025-12-01)
4
12
  - Change default use_hybrid_disposition to False (databricks/databricks-sql-python#714 by @samikshya-db)
5
13
  - Circuit breaker changes using pybreaker (databricks/databricks-sql-python#705 by @nikhilsuri-db)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-sql-connector
3
- Version: 4.2.2
3
+ Version: 4.2.4
4
4
  Summary: Databricks SQL Connector for Python
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -17,13 +17,15 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: 3.14
19
19
  Provides-Extra: pyarrow
20
- Requires-Dist: lz4 (>=4.0.2,<5.0.0)
20
+ Requires-Dist: lz4 (>=4.0.2,<5.0.0) ; python_version >= "3.8" and python_version < "3.14"
21
+ Requires-Dist: lz4 (>=4.4.5,<5.0.0) ; python_version >= "3.14"
21
22
  Requires-Dist: oauthlib (>=3.1.0,<4.0.0)
22
23
  Requires-Dist: openpyxl (>=3.0.10,<4.0.0)
23
- Requires-Dist: pandas (>=1.2.5,<2.3.0) ; python_version >= "3.8" and python_version < "3.13"
24
- Requires-Dist: pandas (>=2.2.3,<2.3.0) ; python_version >= "3.13"
24
+ Requires-Dist: pandas (>=1.2.5,<2.4.0) ; python_version >= "3.8" and python_version < "3.13"
25
+ Requires-Dist: pandas (>=2.2.3,<2.4.0) ; python_version >= "3.13"
25
26
  Requires-Dist: pyarrow (>=14.0.1) ; (python_version >= "3.8" and python_version < "3.13") and (extra == "pyarrow")
26
- Requires-Dist: pyarrow (>=18.0.0) ; (python_version >= "3.13") and (extra == "pyarrow")
27
+ Requires-Dist: pyarrow (>=18.0.0) ; (python_version == "3.13") and (extra == "pyarrow")
28
+ Requires-Dist: pyarrow (>=22.0.0) ; (python_version >= "3.14") and (extra == "pyarrow")
27
29
  Requires-Dist: pybreaker (>=1.0.0,<2.0.0)
28
30
  Requires-Dist: pyjwt (>=2.0.0,<3.0.0)
29
31
  Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "databricks-sql-connector"
3
- version = "4.2.2"
3
+ version = "4.2.4"
4
4
  description = "Databricks SQL Connector for Python"
5
5
  authors = ["Databricks <databricks-sql-connector-maintainers@databricks.com>"]
6
6
  license = "Apache-2.0"
@@ -12,10 +12,13 @@ include = ["CHANGELOG.md"]
12
12
  python = "^3.8.0"
13
13
  thrift = ">=0.16.0,<0.21.0"
14
14
  pandas = [
15
- { version = ">=1.2.5,<2.3.0", python = ">=3.8,<3.13" },
16
- { version = ">=2.2.3,<2.3.0", python = ">=3.13" }
15
+ { version = ">=1.2.5,<2.4.0", python = ">=3.8,<3.13" },
16
+ { version = ">=2.2.3,<2.4.0", python = ">=3.13" }
17
+ ]
18
+ lz4 = [
19
+ { version = "^4.0.2", python = ">=3.8,<3.14" },
20
+ { version = "^4.4.5", python = ">=3.14" }
17
21
  ]
18
- lz4 = "^4.0.2"
19
22
  requests = "^2.18.1"
20
23
  oauthlib = "^3.1.0"
21
24
  openpyxl = "^3.0.10"
@@ -23,7 +26,8 @@ urllib3 = ">=1.26"
23
26
  python-dateutil = "^2.8.0"
24
27
  pyarrow = [
25
28
  { version = ">=14.0.1", python = ">=3.8,<3.13", optional=true },
26
- { version = ">=18.0.0", python = ">=3.13", optional=true }
29
+ { version = ">=18.0.0", python = ">=3.13,<3.14", optional=true },
30
+ { version = ">=22.0.0", python = ">=3.14", optional=true }
27
31
  ]
28
32
  pyjwt = "^2.0.0"
29
33
  pybreaker = "^1.0.0"
@@ -71,7 +71,7 @@ DATETIME = DBAPITypeObject("timestamp")
71
71
  DATE = DBAPITypeObject("date")
72
72
  ROWID = DBAPITypeObject()
73
73
 
74
- __version__ = "4.2.2"
74
+ __version__ = "4.2.4"
75
75
  USER_AGENT_NAME = "PyDatabricksSqlConnector"
76
76
 
77
77
  # These two functions are pyhive legacy
@@ -7,23 +7,6 @@ from urllib.parse import urlparse
7
7
  logger = logging.getLogger(__name__)
8
8
 
9
9
 
10
- def parse_hostname(hostname: str) -> str:
11
- """
12
- Normalize the hostname to include scheme and trailing slash.
13
-
14
- Args:
15
- hostname: The hostname to normalize
16
-
17
- Returns:
18
- Normalized hostname with scheme and trailing slash
19
- """
20
- if not hostname.startswith("http://") and not hostname.startswith("https://"):
21
- hostname = f"https://{hostname}"
22
- if not hostname.endswith("/"):
23
- hostname = f"{hostname}/"
24
- return hostname
25
-
26
-
27
10
  def decode_token(access_token: str) -> Optional[Dict]:
28
11
  """
29
12
  Decode a JWT token without verification to extract claims.
@@ -6,10 +6,10 @@ from urllib.parse import urlencode
6
6
 
7
7
  from databricks.sql.auth.authenticators import AuthProvider
8
8
  from databricks.sql.auth.auth_utils import (
9
- parse_hostname,
10
9
  decode_token,
11
10
  is_same_host,
12
11
  )
12
+ from databricks.sql.common.url_utils import normalize_host_with_protocol
13
13
  from databricks.sql.common.http import HttpMethod
14
14
 
15
15
  logger = logging.getLogger(__name__)
@@ -99,7 +99,7 @@ class TokenFederationProvider(AuthProvider):
99
99
  if not http_client:
100
100
  raise ValueError("http_client is required for TokenFederationProvider")
101
101
 
102
- self.hostname = parse_hostname(hostname)
102
+ self.hostname = normalize_host_with_protocol(hostname)
103
103
  self.external_provider = external_provider
104
104
  self.http_client = http_client
105
105
  self.identity_federation_client_id = identity_federation_client_id
@@ -164,7 +164,7 @@ class TokenFederationProvider(AuthProvider):
164
164
 
165
165
  def _exchange_token(self, access_token: str) -> Token:
166
166
  """Exchange the external token for a Databricks token."""
167
- token_url = f"{self.hostname.rstrip('/')}{self.TOKEN_EXCHANGE_ENDPOINT}"
167
+ token_url = f"{self.hostname}{self.TOKEN_EXCHANGE_ENDPOINT}"
168
168
 
169
169
  data = {
170
170
  "grant_type": self.TOKEN_EXCHANGE_GRANT_TYPE,
@@ -18,6 +18,7 @@ from databricks.sql.exc import (
18
18
  from databricks.sql.common.http_utils import (
19
19
  detect_and_parse_proxy,
20
20
  )
21
+ from databricks.sql.common.url_utils import normalize_host_with_protocol
21
22
 
22
23
  logger = logging.getLogger(__name__)
23
24
 
@@ -66,8 +67,9 @@ class SeaHttpClient:
66
67
  self.auth_provider = auth_provider
67
68
  self.ssl_options = ssl_options
68
69
 
69
- # Build base URL
70
- self.base_url = f"https://{server_hostname}:{self.port}"
70
+ # Build base URL using url_utils for consistent normalization
71
+ normalized_host = normalize_host_with_protocol(server_hostname)
72
+ self.base_url = f"{normalized_host}:{self.port}"
71
73
 
72
74
  # Parse URL for proxy handling
73
75
  parsed_url = urllib.parse.urlparse(self.base_url)
@@ -6,6 +6,7 @@ from concurrent.futures import ThreadPoolExecutor
6
6
  from typing import Dict, Optional, List, Any, TYPE_CHECKING
7
7
 
8
8
  from databricks.sql.common.http import HttpMethod
9
+ from databricks.sql.common.url_utils import normalize_host_with_protocol
9
10
 
10
11
  if TYPE_CHECKING:
11
12
  from databricks.sql.client import Connection
@@ -67,7 +68,8 @@ class FeatureFlagsContext:
67
68
 
68
69
  endpoint_suffix = FEATURE_FLAGS_ENDPOINT_SUFFIX_FORMAT.format(__version__)
69
70
  self._feature_flag_endpoint = (
70
- f"https://{self._connection.session.host}{endpoint_suffix}"
71
+ normalize_host_with_protocol(self._connection.session.host)
72
+ + endpoint_suffix
71
73
  )
72
74
 
73
75
  # Use the provided HTTP client
@@ -0,0 +1,45 @@
1
+ """
2
+ URL utility functions for the Databricks SQL connector.
3
+ """
4
+
5
+
6
+ def normalize_host_with_protocol(host: str) -> str:
7
+ """
8
+ Normalize a connection hostname by ensuring it has a protocol.
9
+
10
+ This is useful for handling cases where users may provide hostnames with or without protocols
11
+ (common with dbt-databricks users copying URLs from their browser).
12
+
13
+ Args:
14
+ host: Connection hostname which may or may not include a protocol prefix (https:// or http://)
15
+ and may or may not have a trailing slash
16
+
17
+ Returns:
18
+ Normalized hostname with protocol prefix and no trailing slashes
19
+
20
+ Examples:
21
+ normalize_host_with_protocol("myserver.com") -> "https://myserver.com"
22
+ normalize_host_with_protocol("https://myserver.com") -> "https://myserver.com"
23
+ normalize_host_with_protocol("HTTPS://myserver.com/") -> "https://myserver.com"
24
+ normalize_host_with_protocol("http://localhost:8080/") -> "http://localhost:8080"
25
+
26
+ Raises:
27
+ ValueError: If host is None or empty string
28
+ """
29
+ # Handle None or empty host
30
+ if not host or not host.strip():
31
+ raise ValueError("Host cannot be None or empty")
32
+
33
+ # Remove trailing slashes
34
+ host = host.rstrip("/")
35
+
36
+ # Add protocol if not present (case-insensitive check)
37
+ host_lower = host.lower()
38
+ if not host_lower.startswith("https://") and not host_lower.startswith("http://"):
39
+ host = f"https://{host}"
40
+ elif host_lower.startswith("https://") or host_lower.startswith("http://"):
41
+ # Normalize protocol to lowercase
42
+ protocol_end = host.index("://") + 3
43
+ host = host[:protocol_end].lower() + host[protocol_end:]
44
+
45
+ return host
@@ -47,6 +47,7 @@ from databricks.sql.telemetry.telemetry_push_client import (
47
47
  TelemetryPushClient,
48
48
  CircuitBreakerTelemetryPushClient,
49
49
  )
50
+ from databricks.sql.common.url_utils import normalize_host_with_protocol
50
51
 
51
52
  if TYPE_CHECKING:
52
53
  from databricks.sql.client import Connection
@@ -278,7 +279,7 @@ class TelemetryClient(BaseTelemetryClient):
278
279
  if self._auth_provider
279
280
  else self.TELEMETRY_UNAUTHENTICATED_PATH
280
281
  )
281
- url = f"https://{self._host_url}{path}"
282
+ url = normalize_host_with_protocol(self._host_url) + path
282
283
 
283
284
  headers = {"Accept": "application/json", "Content-Type": "application/json"}
284
285
 
@@ -542,8 +543,8 @@ class TelemetryClientFactory:
542
543
  logger.debug("Handling unhandled exception: %s", exc_type.__name__)
543
544
 
544
545
  clients_to_close = list(cls._clients.values())
545
- for client in clients_to_close:
546
- client.close()
546
+ for holder in clients_to_close:
547
+ holder.client.close()
547
548
 
548
549
  # Call the original exception handler to maintain normal behavior
549
550
  if cls._original_excepthook: