databricks-sql-connector 4.1.4__tar.gz → 4.1.5__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 (66) hide show
  1. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/CHANGELOG.md +3 -0
  2. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/PKG-INFO +2 -4
  3. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/pyproject.toml +1 -1
  4. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/__init__.py +1 -1
  5. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/common.py +2 -0
  6. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/retry.py +16 -2
  7. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/utils/http_client.py +4 -0
  8. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/thrift_backend.py +4 -0
  9. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/common/unified_http_client.py +1 -0
  10. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/utils.py +3 -0
  11. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/LICENSE +0 -0
  12. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/README.md +0 -0
  13. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/__init__.py +0 -0
  14. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/__init__.py +0 -0
  15. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/auth.py +0 -0
  16. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/auth_utils.py +0 -0
  17. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/authenticators.py +0 -0
  18. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/endpoint.py +0 -0
  19. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/oauth.py +0 -0
  20. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/oauth_http_handler.py +0 -0
  21. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/thrift_http_client.py +0 -0
  22. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/auth/token_federation.py +0 -0
  23. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/databricks_client.py +0 -0
  24. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/backend.py +0 -0
  25. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/models/__init__.py +0 -0
  26. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/models/base.py +0 -0
  27. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/models/requests.py +0 -0
  28. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/models/responses.py +0 -0
  29. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/queue.py +0 -0
  30. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/result_set.py +0 -0
  31. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/utils/constants.py +0 -0
  32. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/utils/conversion.py +0 -0
  33. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/utils/filters.py +0 -0
  34. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/sea/utils/normalize.py +0 -0
  35. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/types.py +0 -0
  36. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/utils/__init__.py +0 -0
  37. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/backend/utils/guid_utils.py +0 -0
  38. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/client.py +0 -0
  39. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/cloudfetch/download_manager.py +0 -0
  40. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/cloudfetch/downloader.py +0 -0
  41. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/common/feature_flag.py +0 -0
  42. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/common/http.py +0 -0
  43. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/common/http_utils.py +0 -0
  44. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/exc.py +0 -0
  45. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/experimental/__init__.py +0 -0
  46. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/experimental/oauth_persistence.py +0 -0
  47. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/parameters/__init__.py +0 -0
  48. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/parameters/native.py +0 -0
  49. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/parameters/py.typed +0 -0
  50. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/py.typed +0 -0
  51. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/result_set.py +0 -0
  52. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/session.py +0 -0
  53. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/latency_logger.py +0 -0
  54. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/models/endpoint_models.py +0 -0
  55. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/models/enums.py +0 -0
  56. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/models/event.py +0 -0
  57. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/models/frontend_logs.py +0 -0
  58. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/telemetry_client.py +0 -0
  59. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/telemetry/utils.py +0 -0
  60. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/TCLIService/TCLIService-remote +0 -0
  61. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/TCLIService/TCLIService.py +0 -0
  62. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/TCLIService/__init__.py +0 -0
  63. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/TCLIService/constants.py +0 -0
  64. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/TCLIService/ttypes.py +0 -0
  65. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/thrift_api/__init__.py +0 -0
  66. {databricks_sql_connector-4.1.4 → databricks_sql_connector-4.1.5}/src/databricks/sql/types.py +0 -0
@@ -1,5 +1,8 @@
1
1
  # Release History
2
2
 
3
+ # 4.1.5 (2026-03-23)
4
+ - Add _retry_server_directed_only mode for Retry-After header compliance (databricks/databricks-sql-python#757 by @sd-db)
5
+
3
6
  # 4.1.4 (2025-10-15)
4
7
  - Add support for Token Federation (databricks/databricks-sql-python#691 by @madhav-db)
5
8
  - Add metric view support (databricks/databricks-sql-python#688 by @shivam2680)
@@ -1,9 +1,8 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.3
2
2
  Name: databricks-sql-connector
3
- Version: 4.1.4
3
+ Version: 4.1.5
4
4
  Summary: Databricks SQL Connector for Python
5
5
  License: Apache-2.0
6
- License-File: LICENSE
7
6
  Author: Databricks
8
7
  Author-email: databricks-sql-connector-maintainers@databricks.com
9
8
  Requires-Python: >=3.8.0,<4.0.0
@@ -15,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
17
16
  Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: Python :: 3.14
19
17
  Provides-Extra: pyarrow
20
18
  Requires-Dist: lz4 (>=4.0.2,<5.0.0)
21
19
  Requires-Dist: oauthlib (>=3.1.0,<4.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "databricks-sql-connector"
3
- version = "4.1.4"
3
+ version = "4.1.5"
4
4
  description = "Databricks SQL Connector for Python"
5
5
  authors = ["Databricks <databricks-sql-connector-maintainers@databricks.com>"]
6
6
  license = "Apache-2.0"
@@ -68,7 +68,7 @@ DATETIME = DBAPITypeObject("timestamp")
68
68
  DATE = DBAPITypeObject("date")
69
69
  ROWID = DBAPITypeObject()
70
70
 
71
- __version__ = "4.1.4"
71
+ __version__ = "4.1.5"
72
72
  USER_AGENT_NAME = "PyDatabricksSqlConnector"
73
73
 
74
74
  # These two functions are pyhive legacy
@@ -47,6 +47,7 @@ class ClientContext:
47
47
  retry_stop_after_attempts_duration: Optional[float] = None,
48
48
  retry_delay_default: Optional[float] = None,
49
49
  retry_dangerous_codes: Optional[List[int]] = None,
50
+ respect_server_retry_after_header: Optional[bool] = None,
50
51
  proxy_auth_method: Optional[str] = None,
51
52
  pool_connections: Optional[int] = None,
52
53
  pool_maxsize: Optional[int] = None,
@@ -79,6 +80,7 @@ class ClientContext:
79
80
  )
80
81
  self.retry_delay_default = retry_delay_default or 5.0
81
82
  self.retry_dangerous_codes = retry_dangerous_codes or []
83
+ self.respect_server_retry_after_header = bool(respect_server_retry_after_header)
82
84
  self.proxy_auth_method = proxy_auth_method
83
85
  self.pool_connections = pool_connections or 10
84
86
  self.pool_maxsize = pool_maxsize or 20
@@ -94,6 +94,7 @@ class DatabricksRetryPolicy(Retry):
94
94
  stop_after_attempts_duration: float,
95
95
  delay_default: float,
96
96
  force_dangerous_codes: List[int],
97
+ respect_server_retry_after_header: bool = False,
97
98
  urllib3_kwargs: dict = {},
98
99
  ):
99
100
  # These values do not change from one command to the next
@@ -103,6 +104,7 @@ class DatabricksRetryPolicy(Retry):
103
104
  self.stop_after_attempts_duration = stop_after_attempts_duration
104
105
  self._delay_default = delay_default
105
106
  self.force_dangerous_codes = force_dangerous_codes
107
+ self.respect_server_retry_after_header = respect_server_retry_after_header
106
108
 
107
109
  # the urllib3 kwargs are a mix of configuration (some of which we override)
108
110
  # and counters like `total` or `connect` which may change between successive retries
@@ -202,6 +204,7 @@ class DatabricksRetryPolicy(Retry):
202
204
  stop_after_attempts_duration=self.stop_after_attempts_duration,
203
205
  delay_default=self.delay_default,
204
206
  force_dangerous_codes=self.force_dangerous_codes,
207
+ respect_server_retry_after_header=self.respect_server_retry_after_header,
205
208
  urllib3_kwargs={},
206
209
  )
207
210
 
@@ -323,7 +326,9 @@ class DatabricksRetryPolicy(Retry):
323
326
 
324
327
  return proposed_backoff
325
328
 
326
- def should_retry(self, method: str, status_code: int) -> Tuple[bool, str]:
329
+ def should_retry(
330
+ self, method: str, status_code: int, has_retry_after: bool = False
331
+ ) -> Tuple[bool, str]:
327
332
  """This method encapsulates the connector's approach to retries.
328
333
 
329
334
  We always retry a request unless one of these conditions is met:
@@ -381,6 +386,15 @@ class DatabricksRetryPolicy(Retry):
381
386
  if not self._is_method_retryable(method):
382
387
  return False, "Only POST requests are retried"
383
388
 
389
+ # When respect_server_retry_after_header is enabled, only retry when the
390
+ # server explicitly signals it's safe via a Retry-After header. This prevents
391
+ # duplicate side effects for non-idempotent operations.
392
+ if self.respect_server_retry_after_header and not has_retry_after:
393
+ return (
394
+ False,
395
+ "respect_server_retry_after_header mode: no Retry-After header present",
396
+ )
397
+
384
398
  # Request failed with 404 and was a GetOperationStatus. This is not recoverable. Don't retry.
385
399
  if status_code == 404 and self.command_type == CommandType.GET_OPERATION_STATUS:
386
400
  return (
@@ -450,7 +464,7 @@ class DatabricksRetryPolicy(Retry):
450
464
  Logs a debug message if the request will be retried
451
465
  """
452
466
 
453
- should_retry, msg = self.should_retry(method, status_code)
467
+ should_retry, msg = self.should_retry(method, status_code, has_retry_after)
454
468
 
455
469
  if should_retry:
456
470
  logger.debug(msg)
@@ -90,6 +90,9 @@ class SeaHttpClient:
90
90
  )
91
91
  self._retry_delay_default = kwargs.get("_retry_delay_default", 5.0)
92
92
  self.force_dangerous_codes = kwargs.get("_retry_dangerous_codes", [])
93
+ self._respect_server_retry_after_header = kwargs.get(
94
+ "_respect_server_retry_after_header", False
95
+ )
93
96
 
94
97
  # Connection pooling settings
95
98
  self.max_connections = kwargs.get("max_connections", 10)
@@ -114,6 +117,7 @@ class SeaHttpClient:
114
117
  stop_after_attempts_duration=self._retry_stop_after_attempts_duration,
115
118
  delay_default=self._retry_delay_default,
116
119
  force_dangerous_codes=self.force_dangerous_codes,
120
+ respect_server_retry_after_header=self._respect_server_retry_after_header,
117
121
  urllib3_kwargs=urllib3_kwargs,
118
122
  )
119
123
  else:
@@ -189,6 +189,9 @@ class ThriftDatabricksClient(DatabricksClient):
189
189
  " This behaviour is deprecated and will be removed in a future release."
190
190
  )
191
191
  self.force_dangerous_codes = kwargs.get("_retry_dangerous_codes", [])
192
+ self._respect_server_retry_after_header = kwargs.get(
193
+ "_respect_server_retry_after_header", False
194
+ )
192
195
 
193
196
  additional_transport_args = {}
194
197
 
@@ -215,6 +218,7 @@ class ThriftDatabricksClient(DatabricksClient):
215
218
  stop_after_attempts_duration=self._retry_stop_after_attempts_duration,
216
219
  delay_default=self._retry_delay_default,
217
220
  force_dangerous_codes=self.force_dangerous_codes,
221
+ respect_server_retry_after_header=self._respect_server_retry_after_header,
218
222
  urllib3_kwargs=urllib3_kwargs,
219
223
  )
220
224
 
@@ -99,6 +99,7 @@ class UnifiedHttpClient:
99
99
  stop_after_attempts_duration=self.config.retry_stop_after_attempts_duration,
100
100
  delay_default=self.config.retry_delay_default,
101
101
  force_dangerous_codes=self.config.retry_dangerous_codes,
102
+ respect_server_retry_after_header=self.config.respect_server_retry_after_header,
102
103
  )
103
104
 
104
105
  # Initialize the required attributes that DatabricksRetryPolicy expects
@@ -919,6 +919,9 @@ def build_client_context(server_hostname: str, version: str, **kwargs):
919
919
  ),
920
920
  retry_delay_default=kwargs.get("_retry_delay_default"),
921
921
  retry_dangerous_codes=kwargs.get("_retry_dangerous_codes"),
922
+ respect_server_retry_after_header=kwargs.get(
923
+ "_respect_server_retry_after_header"
924
+ ),
922
925
  proxy_auth_method=kwargs.get("_proxy_auth_method"),
923
926
  pool_connections=kwargs.get("_pool_connections"),
924
927
  pool_maxsize=kwargs.get("_pool_maxsize"),