databricks-sql-connector 4.2.1__tar.gz → 4.2.2__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.
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/CHANGELOG.md +7 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/PKG-INFO +3 -2
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/README.md +1 -1
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/pyproject.toml +6 -2
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/__init__.py +1 -1
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/common.py +2 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/backend.py +1 -1
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/thrift_backend.py +34 -38
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/client.py +35 -3
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/common/feature_flag.py +5 -3
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/common/unified_http_client.py +46 -1
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/exc.py +33 -4
- databricks_sql_connector-4.2.2/src/databricks/sql/telemetry/circuit_breaker_manager.py +112 -0
- databricks_sql_connector-4.2.2/src/databricks/sql/telemetry/latency_logger.py +220 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/telemetry_client.py +215 -61
- databricks_sql_connector-4.2.2/src/databricks/sql/telemetry/telemetry_push_client.py +201 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/utils.py +3 -0
- databricks_sql_connector-4.2.1/src/databricks/sql/telemetry/latency_logger.py +0 -216
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/LICENSE +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/auth.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/auth_utils.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/authenticators.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/endpoint.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/oauth.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/oauth_http_handler.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/retry.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/thrift_http_client.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/token_federation.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/databricks_client.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/models/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/models/base.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/models/requests.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/models/responses.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/queue.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/result_set.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/utils/constants.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/utils/conversion.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/utils/filters.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/utils/http_client.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/sea/utils/normalize.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/types.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/utils/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/backend/utils/guid_utils.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/cloudfetch/download_manager.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/cloudfetch/downloader.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/common/http.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/common/http_utils.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/experimental/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/experimental/oauth_persistence.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/parameters/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/parameters/native.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/parameters/py.typed +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/py.typed +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/result_set.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/session.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/models/endpoint_models.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/models/enums.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/models/event.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/models/frontend_logs.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/telemetry/utils.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/TCLIService/TCLIService-remote +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/TCLIService/TCLIService.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/TCLIService/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/TCLIService/constants.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/TCLIService/ttypes.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/thrift_api/__init__.py +0 -0
- {databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/types.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
# 4.2.2 (2025-12-01)
|
|
4
|
+
- Change default use_hybrid_disposition to False (databricks/databricks-sql-python#714 by @samikshya-db)
|
|
5
|
+
- Circuit breaker changes using pybreaker (databricks/databricks-sql-python#705 by @nikhilsuri-db)
|
|
6
|
+
- perf: Optimize telemetry latency logging to reduce overhead (databricks/databricks-sql-python#715 by @samikshya-db)
|
|
7
|
+
- basic e2e test for force telemetry verification (databricks/databricks-sql-python#708 by @nikhilsuri-db)
|
|
8
|
+
- Telemetry is ON by default to track connection stats. (Note : This strictly excludes PII, query text, and results) (databricks/databricks-sql-python#717 by @samikshya-db)
|
|
9
|
+
|
|
3
10
|
# 4.2.1 (2025-11-20)
|
|
4
11
|
- Ignore transactions by default (databricks/databricks-sql-python#711 by @jayantsing-db)
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: databricks-sql-connector
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.2
|
|
4
4
|
Summary: Databricks SQL Connector for Python
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -24,6 +24,7 @@ Requires-Dist: pandas (>=1.2.5,<2.3.0) ; python_version >= "3.8" and python_vers
|
|
|
24
24
|
Requires-Dist: pandas (>=2.2.3,<2.3.0) ; python_version >= "3.13"
|
|
25
25
|
Requires-Dist: pyarrow (>=14.0.1) ; (python_version >= "3.8" and python_version < "3.13") and (extra == "pyarrow")
|
|
26
26
|
Requires-Dist: pyarrow (>=18.0.0) ; (python_version >= "3.13") and (extra == "pyarrow")
|
|
27
|
+
Requires-Dist: pybreaker (>=1.0.0,<2.0.0)
|
|
27
28
|
Requires-Dist: pyjwt (>=2.0.0,<3.0.0)
|
|
28
29
|
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
|
29
30
|
Requires-Dist: requests (>=2.18.1,<3.0.0)
|
|
@@ -48,7 +49,7 @@ You are welcome to file an issue here for general use cases. You can also contac
|
|
|
48
49
|
|
|
49
50
|
## Requirements
|
|
50
51
|
|
|
51
|
-
Python 3.
|
|
52
|
+
Python 3.9 or above is required.
|
|
52
53
|
|
|
53
54
|
## Documentation
|
|
54
55
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "databricks-sql-connector"
|
|
3
|
-
version = "4.2.
|
|
3
|
+
version = "4.2.2"
|
|
4
4
|
description = "Databricks SQL Connector for Python"
|
|
5
5
|
authors = ["Databricks <databricks-sql-connector-maintainers@databricks.com>"]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -26,6 +26,7 @@ pyarrow = [
|
|
|
26
26
|
{ version = ">=18.0.0", python = ">=3.13", optional=true }
|
|
27
27
|
]
|
|
28
28
|
pyjwt = "^2.0.0"
|
|
29
|
+
pybreaker = "^1.0.0"
|
|
29
30
|
requests-kerberos = {version = "^0.15.0", optional = true}
|
|
30
31
|
|
|
31
32
|
|
|
@@ -61,7 +62,10 @@ exclude = ['ttypes\.py$', 'TCLIService\.py$']
|
|
|
61
62
|
exclude = '/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|thrift_api)/'
|
|
62
63
|
|
|
63
64
|
[tool.pytest.ini_options]
|
|
64
|
-
markers =
|
|
65
|
+
markers = [
|
|
66
|
+
"reviewed: Test case has been reviewed by Databricks",
|
|
67
|
+
"serial: Tests that must run serially (not parallelized)"
|
|
68
|
+
]
|
|
65
69
|
minversion = "6.0"
|
|
66
70
|
log_cli = "false"
|
|
67
71
|
log_cli_level = "INFO"
|
{databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/auth/common.py
RENAMED
|
@@ -51,6 +51,7 @@ class ClientContext:
|
|
|
51
51
|
pool_connections: Optional[int] = None,
|
|
52
52
|
pool_maxsize: Optional[int] = None,
|
|
53
53
|
user_agent: Optional[str] = None,
|
|
54
|
+
telemetry_circuit_breaker_enabled: Optional[bool] = True,
|
|
54
55
|
):
|
|
55
56
|
self.hostname = hostname
|
|
56
57
|
self.access_token = access_token
|
|
@@ -83,6 +84,7 @@ class ClientContext:
|
|
|
83
84
|
self.pool_connections = pool_connections or 10
|
|
84
85
|
self.pool_maxsize = pool_maxsize or 20
|
|
85
86
|
self.user_agent = user_agent
|
|
87
|
+
self.telemetry_circuit_breaker_enabled = bool(telemetry_circuit_breaker_enabled)
|
|
86
88
|
|
|
87
89
|
|
|
88
90
|
def get_effective_azure_login_app_id(hostname) -> str:
|
|
@@ -157,7 +157,7 @@ class SeaDatabricksClient(DatabricksClient):
|
|
|
157
157
|
"_use_arrow_native_complex_types", True
|
|
158
158
|
)
|
|
159
159
|
|
|
160
|
-
self.use_hybrid_disposition = kwargs.get("use_hybrid_disposition",
|
|
160
|
+
self.use_hybrid_disposition = kwargs.get("use_hybrid_disposition", False)
|
|
161
161
|
self.use_cloud_fetch = kwargs.get("use_cloud_fetch", True)
|
|
162
162
|
|
|
163
163
|
# Extract warehouse ID from http_path
|
|
@@ -163,6 +163,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
163
163
|
else:
|
|
164
164
|
raise ValueError("No valid connection settings.")
|
|
165
165
|
|
|
166
|
+
self._host = server_hostname
|
|
166
167
|
self._initialize_retry_args(kwargs)
|
|
167
168
|
self._use_arrow_native_complex_types = kwargs.get(
|
|
168
169
|
"_use_arrow_native_complex_types", True
|
|
@@ -279,14 +280,14 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
279
280
|
)
|
|
280
281
|
|
|
281
282
|
@staticmethod
|
|
282
|
-
def _check_response_for_error(response,
|
|
283
|
+
def _check_response_for_error(response, host_url=None):
|
|
283
284
|
if response.status and response.status.statusCode in [
|
|
284
285
|
ttypes.TStatusCode.ERROR_STATUS,
|
|
285
286
|
ttypes.TStatusCode.INVALID_HANDLE_STATUS,
|
|
286
287
|
]:
|
|
287
288
|
raise DatabaseError(
|
|
288
289
|
response.status.errorMessage,
|
|
289
|
-
|
|
290
|
+
host_url=host_url,
|
|
290
291
|
)
|
|
291
292
|
|
|
292
293
|
@staticmethod
|
|
@@ -340,7 +341,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
340
341
|
network_request_error = RequestError(
|
|
341
342
|
user_friendly_error_message,
|
|
342
343
|
full_error_info_context,
|
|
343
|
-
self.
|
|
344
|
+
self._host,
|
|
344
345
|
error_info.error,
|
|
345
346
|
)
|
|
346
347
|
logger.info(network_request_error.message_with_context())
|
|
@@ -461,13 +462,12 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
461
462
|
errno.ECONNRESET, # | 104 | 54 |
|
|
462
463
|
errno.ETIMEDOUT, # | 110 | 60 |
|
|
463
464
|
]
|
|
465
|
+
# fmt: on
|
|
464
466
|
|
|
465
467
|
gos_name = TCLIServiceClient.GetOperationStatus.__name__
|
|
466
468
|
# retry on timeout. Happens a lot in Azure and it is safe as data has not been sent to server yet
|
|
467
469
|
if method.__name__ == gos_name or err.errno == errno.ETIMEDOUT:
|
|
468
470
|
retry_delay = bound_retry_delay(attempt, self._retry_delay_default)
|
|
469
|
-
|
|
470
|
-
# fmt: on
|
|
471
471
|
log_string = f"{gos_name} failed with code {err.errno} and will attempt to retry"
|
|
472
472
|
if err.errno in info_errs:
|
|
473
473
|
logger.info(log_string)
|
|
@@ -516,9 +516,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
516
516
|
if not isinstance(response_or_error_info, RequestErrorInfo):
|
|
517
517
|
# log nothing here, presume that main request logging covers
|
|
518
518
|
response = response_or_error_info
|
|
519
|
-
ThriftDatabricksClient._check_response_for_error(
|
|
520
|
-
response, self._session_id_hex
|
|
521
|
-
)
|
|
519
|
+
ThriftDatabricksClient._check_response_for_error(response, self._host)
|
|
522
520
|
return response
|
|
523
521
|
|
|
524
522
|
error_info = response_or_error_info
|
|
@@ -533,7 +531,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
533
531
|
"Error: expected server to use a protocol version >= "
|
|
534
532
|
"SPARK_CLI_SERVICE_PROTOCOL_V2, "
|
|
535
533
|
"instead got: {}".format(protocol_version),
|
|
536
|
-
|
|
534
|
+
host_url=self._host,
|
|
537
535
|
)
|
|
538
536
|
|
|
539
537
|
def _check_initial_namespace(self, catalog, schema, response):
|
|
@@ -547,7 +545,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
547
545
|
raise InvalidServerResponseError(
|
|
548
546
|
"Setting initial namespace not supported by the DBR version, "
|
|
549
547
|
"Please use a Databricks SQL endpoint or a cluster with DBR >= 9.0.",
|
|
550
|
-
|
|
548
|
+
host_url=self._host,
|
|
551
549
|
)
|
|
552
550
|
|
|
553
551
|
if catalog:
|
|
@@ -555,7 +553,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
555
553
|
raise InvalidServerResponseError(
|
|
556
554
|
"Unexpected response from server: Trying to set initial catalog to {}, "
|
|
557
555
|
+ "but server does not support multiple catalogs.".format(catalog), # type: ignore
|
|
558
|
-
|
|
556
|
+
host_url=self._host,
|
|
559
557
|
)
|
|
560
558
|
|
|
561
559
|
def _check_session_configuration(self, session_configuration):
|
|
@@ -570,7 +568,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
570
568
|
TIMESTAMP_AS_STRING_CONFIG,
|
|
571
569
|
session_configuration[TIMESTAMP_AS_STRING_CONFIG],
|
|
572
570
|
),
|
|
573
|
-
|
|
571
|
+
host_url=self._host,
|
|
574
572
|
)
|
|
575
573
|
|
|
576
574
|
def open_session(self, session_configuration, catalog, schema) -> SessionId:
|
|
@@ -639,7 +637,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
639
637
|
and guid_to_hex_id(op_handle.operationId.guid),
|
|
640
638
|
"diagnostic-info": get_operations_resp.diagnosticInfo,
|
|
641
639
|
},
|
|
642
|
-
|
|
640
|
+
host_url=self._host,
|
|
643
641
|
)
|
|
644
642
|
else:
|
|
645
643
|
raise ServerOperationError(
|
|
@@ -649,7 +647,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
649
647
|
and guid_to_hex_id(op_handle.operationId.guid),
|
|
650
648
|
"diagnostic-info": None,
|
|
651
649
|
},
|
|
652
|
-
|
|
650
|
+
host_url=self._host,
|
|
653
651
|
)
|
|
654
652
|
elif get_operations_resp.operationState == ttypes.TOperationState.CLOSED_STATE:
|
|
655
653
|
raise DatabaseError(
|
|
@@ -660,7 +658,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
660
658
|
"operation-id": op_handle
|
|
661
659
|
and guid_to_hex_id(op_handle.operationId.guid)
|
|
662
660
|
},
|
|
663
|
-
|
|
661
|
+
host_url=self._host,
|
|
664
662
|
)
|
|
665
663
|
|
|
666
664
|
def _poll_for_status(self, op_handle):
|
|
@@ -683,7 +681,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
683
681
|
else:
|
|
684
682
|
raise OperationalError(
|
|
685
683
|
"Unsupported TRowSet instance {}".format(t_row_set),
|
|
686
|
-
|
|
684
|
+
host_url=self._host,
|
|
687
685
|
)
|
|
688
686
|
return convert_decimals_in_arrow_table(arrow_table, description), num_rows
|
|
689
687
|
|
|
@@ -692,7 +690,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
692
690
|
return self.make_request(self._client.GetResultSetMetadata, req)
|
|
693
691
|
|
|
694
692
|
@staticmethod
|
|
695
|
-
def _hive_schema_to_arrow_schema(t_table_schema,
|
|
693
|
+
def _hive_schema_to_arrow_schema(t_table_schema, host_url=None):
|
|
696
694
|
def map_type(t_type_entry):
|
|
697
695
|
if t_type_entry.primitiveEntry:
|
|
698
696
|
return {
|
|
@@ -724,7 +722,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
724
722
|
# even for complex types
|
|
725
723
|
raise OperationalError(
|
|
726
724
|
"Thrift protocol error: t_type_entry not a primitiveEntry",
|
|
727
|
-
|
|
725
|
+
host_url=host_url,
|
|
728
726
|
)
|
|
729
727
|
|
|
730
728
|
def convert_col(t_column_desc):
|
|
@@ -735,7 +733,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
735
733
|
return pyarrow.schema([convert_col(col) for col in t_table_schema.columns])
|
|
736
734
|
|
|
737
735
|
@staticmethod
|
|
738
|
-
def _col_to_description(col, field=None,
|
|
736
|
+
def _col_to_description(col, field=None, host_url=None):
|
|
739
737
|
type_entry = col.typeDesc.types[0]
|
|
740
738
|
|
|
741
739
|
if type_entry.primitiveEntry:
|
|
@@ -745,7 +743,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
745
743
|
else:
|
|
746
744
|
raise OperationalError(
|
|
747
745
|
"Thrift protocol error: t_type_entry not a primitiveEntry",
|
|
748
|
-
|
|
746
|
+
host_url=host_url,
|
|
749
747
|
)
|
|
750
748
|
|
|
751
749
|
if type_entry.primitiveEntry.type == ttypes.TTypeId.DECIMAL_TYPE:
|
|
@@ -759,7 +757,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
759
757
|
raise OperationalError(
|
|
760
758
|
"Decimal type did not provide typeQualifier precision, scale in "
|
|
761
759
|
"primitiveEntry {}".format(type_entry.primitiveEntry),
|
|
762
|
-
|
|
760
|
+
host_url=host_url,
|
|
763
761
|
)
|
|
764
762
|
else:
|
|
765
763
|
precision, scale = None, None
|
|
@@ -778,9 +776,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
778
776
|
return col.columnName, cleaned_type, None, None, precision, scale, None
|
|
779
777
|
|
|
780
778
|
@staticmethod
|
|
781
|
-
def _hive_schema_to_description(
|
|
782
|
-
t_table_schema, schema_bytes=None, session_id_hex=None
|
|
783
|
-
):
|
|
779
|
+
def _hive_schema_to_description(t_table_schema, schema_bytes=None, host_url=None):
|
|
784
780
|
field_dict = {}
|
|
785
781
|
if pyarrow and schema_bytes:
|
|
786
782
|
try:
|
|
@@ -795,7 +791,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
795
791
|
ThriftDatabricksClient._col_to_description(
|
|
796
792
|
col,
|
|
797
793
|
field_dict.get(col.columnName) if field_dict else None,
|
|
798
|
-
|
|
794
|
+
host_url,
|
|
799
795
|
)
|
|
800
796
|
for col in t_table_schema.columns
|
|
801
797
|
]
|
|
@@ -818,7 +814,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
818
814
|
t_result_set_metadata_resp.resultFormat
|
|
819
815
|
]
|
|
820
816
|
),
|
|
821
|
-
|
|
817
|
+
host_url=self._host,
|
|
822
818
|
)
|
|
823
819
|
direct_results = resp.directResults
|
|
824
820
|
has_been_closed_server_side = direct_results and direct_results.closeOperation
|
|
@@ -833,7 +829,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
833
829
|
schema_bytes = (
|
|
834
830
|
t_result_set_metadata_resp.arrowSchema
|
|
835
831
|
or self._hive_schema_to_arrow_schema(
|
|
836
|
-
t_result_set_metadata_resp.schema, self.
|
|
832
|
+
t_result_set_metadata_resp.schema, self._host
|
|
837
833
|
)
|
|
838
834
|
.serialize()
|
|
839
835
|
.to_pybytes()
|
|
@@ -844,7 +840,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
844
840
|
description = self._hive_schema_to_description(
|
|
845
841
|
t_result_set_metadata_resp.schema,
|
|
846
842
|
schema_bytes,
|
|
847
|
-
self.
|
|
843
|
+
self._host,
|
|
848
844
|
)
|
|
849
845
|
|
|
850
846
|
lz4_compressed = t_result_set_metadata_resp.lz4Compressed
|
|
@@ -895,7 +891,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
895
891
|
schema_bytes = (
|
|
896
892
|
t_result_set_metadata_resp.arrowSchema
|
|
897
893
|
or self._hive_schema_to_arrow_schema(
|
|
898
|
-
t_result_set_metadata_resp.schema, self.
|
|
894
|
+
t_result_set_metadata_resp.schema, self._host
|
|
899
895
|
)
|
|
900
896
|
.serialize()
|
|
901
897
|
.to_pybytes()
|
|
@@ -906,7 +902,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
906
902
|
description = self._hive_schema_to_description(
|
|
907
903
|
t_result_set_metadata_resp.schema,
|
|
908
904
|
schema_bytes,
|
|
909
|
-
self.
|
|
905
|
+
self._host,
|
|
910
906
|
)
|
|
911
907
|
|
|
912
908
|
lz4_compressed = t_result_set_metadata_resp.lz4Compressed
|
|
@@ -971,27 +967,27 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
971
967
|
return state
|
|
972
968
|
|
|
973
969
|
@staticmethod
|
|
974
|
-
def _check_direct_results_for_error(t_spark_direct_results,
|
|
970
|
+
def _check_direct_results_for_error(t_spark_direct_results, host_url=None):
|
|
975
971
|
if t_spark_direct_results:
|
|
976
972
|
if t_spark_direct_results.operationStatus:
|
|
977
973
|
ThriftDatabricksClient._check_response_for_error(
|
|
978
974
|
t_spark_direct_results.operationStatus,
|
|
979
|
-
|
|
975
|
+
host_url,
|
|
980
976
|
)
|
|
981
977
|
if t_spark_direct_results.resultSetMetadata:
|
|
982
978
|
ThriftDatabricksClient._check_response_for_error(
|
|
983
979
|
t_spark_direct_results.resultSetMetadata,
|
|
984
|
-
|
|
980
|
+
host_url,
|
|
985
981
|
)
|
|
986
982
|
if t_spark_direct_results.resultSet:
|
|
987
983
|
ThriftDatabricksClient._check_response_for_error(
|
|
988
984
|
t_spark_direct_results.resultSet,
|
|
989
|
-
|
|
985
|
+
host_url,
|
|
990
986
|
)
|
|
991
987
|
if t_spark_direct_results.closeOperation:
|
|
992
988
|
ThriftDatabricksClient._check_response_for_error(
|
|
993
989
|
t_spark_direct_results.closeOperation,
|
|
994
|
-
|
|
990
|
+
host_url,
|
|
995
991
|
)
|
|
996
992
|
|
|
997
993
|
def execute_command(
|
|
@@ -1260,7 +1256,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
1260
1256
|
raise ValueError(f"Invalid Thrift handle: {resp.operationHandle}")
|
|
1261
1257
|
|
|
1262
1258
|
cursor.active_command_id = command_id
|
|
1263
|
-
self._check_direct_results_for_error(resp.directResults, self.
|
|
1259
|
+
self._check_direct_results_for_error(resp.directResults, self._host)
|
|
1264
1260
|
|
|
1265
1261
|
final_operation_state = self._wait_until_command_done(
|
|
1266
1262
|
resp.operationHandle,
|
|
@@ -1275,7 +1271,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
1275
1271
|
raise ValueError(f"Invalid Thrift handle: {resp.operationHandle}")
|
|
1276
1272
|
|
|
1277
1273
|
cursor.active_command_id = command_id
|
|
1278
|
-
self._check_direct_results_for_error(resp.directResults, self.
|
|
1274
|
+
self._check_direct_results_for_error(resp.directResults, self._host)
|
|
1279
1275
|
|
|
1280
1276
|
def fetch_results(
|
|
1281
1277
|
self,
|
|
@@ -1313,7 +1309,7 @@ class ThriftDatabricksClient(DatabricksClient):
|
|
|
1313
1309
|
"fetch_results failed due to inconsistency in the state between the client and the server. Expected results to start from {} but they instead start at {}, some result batches must have been skipped".format(
|
|
1314
1310
|
expected_row_start_offset, resp.results.startRowOffset
|
|
1315
1311
|
),
|
|
1316
|
-
|
|
1312
|
+
host_url=self._host,
|
|
1317
1313
|
)
|
|
1318
1314
|
|
|
1319
1315
|
queue = ThriftResultSetQueueFactory.build_queue(
|
{databricks_sql_connector-4.2.1 → databricks_sql_connector-4.2.2}/src/databricks/sql/client.py
RENAMED
|
@@ -328,7 +328,7 @@ class Connection:
|
|
|
328
328
|
self.ignore_transactions = ignore_transactions
|
|
329
329
|
|
|
330
330
|
self.force_enable_telemetry = kwargs.get("force_enable_telemetry", False)
|
|
331
|
-
self.enable_telemetry = kwargs.get("enable_telemetry",
|
|
331
|
+
self.enable_telemetry = kwargs.get("enable_telemetry", True)
|
|
332
332
|
self.telemetry_enabled = TelemetryHelper.is_telemetry_enabled(self)
|
|
333
333
|
|
|
334
334
|
TelemetryClientFactory.initialize_telemetry_client(
|
|
@@ -341,7 +341,7 @@ class Connection:
|
|
|
341
341
|
)
|
|
342
342
|
|
|
343
343
|
self._telemetry_client = TelemetryClientFactory.get_telemetry_client(
|
|
344
|
-
|
|
344
|
+
host_url=self.session.host
|
|
345
345
|
)
|
|
346
346
|
|
|
347
347
|
# Determine proxy usage
|
|
@@ -391,6 +391,7 @@ class Connection:
|
|
|
391
391
|
self._telemetry_client.export_initial_telemetry_log(
|
|
392
392
|
driver_connection_params=driver_connection_params,
|
|
393
393
|
user_agent=self.session.useragent_header,
|
|
394
|
+
session_id=self.get_session_id_hex(),
|
|
394
395
|
)
|
|
395
396
|
|
|
396
397
|
def _set_use_inline_params_with_warning(self, value: Union[bool, str]):
|
|
@@ -494,6 +495,7 @@ class Connection:
|
|
|
494
495
|
if not self.open:
|
|
495
496
|
raise InterfaceError(
|
|
496
497
|
"Cannot create cursor from closed connection",
|
|
498
|
+
host_url=self.session.host,
|
|
497
499
|
session_id_hex=self.get_session_id_hex(),
|
|
498
500
|
)
|
|
499
501
|
|
|
@@ -521,7 +523,7 @@ class Connection:
|
|
|
521
523
|
except Exception as e:
|
|
522
524
|
logger.error(f"Attempt to close session raised a local exception: {e}")
|
|
523
525
|
|
|
524
|
-
TelemetryClientFactory.close(self.
|
|
526
|
+
TelemetryClientFactory.close(host_url=self.session.host)
|
|
525
527
|
|
|
526
528
|
# Close HTTP client that was created by this connection
|
|
527
529
|
if self.http_client:
|
|
@@ -546,6 +548,7 @@ class Connection:
|
|
|
546
548
|
if not self.open:
|
|
547
549
|
raise InterfaceError(
|
|
548
550
|
"Cannot get autocommit on closed connection",
|
|
551
|
+
host_url=self.session.host,
|
|
549
552
|
session_id_hex=self.get_session_id_hex(),
|
|
550
553
|
)
|
|
551
554
|
|
|
@@ -578,6 +581,7 @@ class Connection:
|
|
|
578
581
|
if not self.open:
|
|
579
582
|
raise InterfaceError(
|
|
580
583
|
"Cannot set autocommit on closed connection",
|
|
584
|
+
host_url=self.session.host,
|
|
581
585
|
session_id_hex=self.get_session_id_hex(),
|
|
582
586
|
)
|
|
583
587
|
|
|
@@ -600,6 +604,7 @@ class Connection:
|
|
|
600
604
|
"operation": "set_autocommit",
|
|
601
605
|
"autocommit_value": value,
|
|
602
606
|
},
|
|
607
|
+
host_url=self.session.host,
|
|
603
608
|
session_id_hex=self.get_session_id_hex(),
|
|
604
609
|
) from e
|
|
605
610
|
finally:
|
|
@@ -627,6 +632,7 @@ class Connection:
|
|
|
627
632
|
raise TransactionError(
|
|
628
633
|
"No result returned from SET AUTOCOMMIT query",
|
|
629
634
|
context={"operation": "fetch_autocommit"},
|
|
635
|
+
host_url=self.session.host,
|
|
630
636
|
session_id_hex=self.get_session_id_hex(),
|
|
631
637
|
)
|
|
632
638
|
|
|
@@ -647,6 +653,7 @@ class Connection:
|
|
|
647
653
|
raise TransactionError(
|
|
648
654
|
f"Failed to fetch autocommit state from server: {e.message}",
|
|
649
655
|
context={**e.context, "operation": "fetch_autocommit"},
|
|
656
|
+
host_url=self.session.host,
|
|
650
657
|
session_id_hex=self.get_session_id_hex(),
|
|
651
658
|
) from e
|
|
652
659
|
finally:
|
|
@@ -680,6 +687,7 @@ class Connection:
|
|
|
680
687
|
if not self.open:
|
|
681
688
|
raise InterfaceError(
|
|
682
689
|
"Cannot commit on closed connection",
|
|
690
|
+
host_url=self.session.host,
|
|
683
691
|
session_id_hex=self.get_session_id_hex(),
|
|
684
692
|
)
|
|
685
693
|
|
|
@@ -692,6 +700,7 @@ class Connection:
|
|
|
692
700
|
raise TransactionError(
|
|
693
701
|
f"Failed to commit transaction: {e.message}",
|
|
694
702
|
context={**e.context, "operation": "commit"},
|
|
703
|
+
host_url=self.session.host,
|
|
695
704
|
session_id_hex=self.get_session_id_hex(),
|
|
696
705
|
) from e
|
|
697
706
|
finally:
|
|
@@ -725,12 +734,14 @@ class Connection:
|
|
|
725
734
|
if self.ignore_transactions:
|
|
726
735
|
raise NotSupportedError(
|
|
727
736
|
"Transactions are not supported on Databricks",
|
|
737
|
+
host_url=self.session.host,
|
|
728
738
|
session_id_hex=self.get_session_id_hex(),
|
|
729
739
|
)
|
|
730
740
|
|
|
731
741
|
if not self.open:
|
|
732
742
|
raise InterfaceError(
|
|
733
743
|
"Cannot rollback on closed connection",
|
|
744
|
+
host_url=self.session.host,
|
|
734
745
|
session_id_hex=self.get_session_id_hex(),
|
|
735
746
|
)
|
|
736
747
|
|
|
@@ -743,6 +754,7 @@ class Connection:
|
|
|
743
754
|
raise TransactionError(
|
|
744
755
|
f"Failed to rollback transaction: {e.message}",
|
|
745
756
|
context={**e.context, "operation": "rollback"},
|
|
757
|
+
host_url=self.session.host,
|
|
746
758
|
session_id_hex=self.get_session_id_hex(),
|
|
747
759
|
) from e
|
|
748
760
|
finally:
|
|
@@ -767,6 +779,7 @@ class Connection:
|
|
|
767
779
|
if not self.open:
|
|
768
780
|
raise InterfaceError(
|
|
769
781
|
"Cannot get transaction isolation on closed connection",
|
|
782
|
+
host_url=self.session.host,
|
|
770
783
|
session_id_hex=self.get_session_id_hex(),
|
|
771
784
|
)
|
|
772
785
|
|
|
@@ -793,6 +806,7 @@ class Connection:
|
|
|
793
806
|
if not self.open:
|
|
794
807
|
raise InterfaceError(
|
|
795
808
|
"Cannot set transaction isolation on closed connection",
|
|
809
|
+
host_url=self.session.host,
|
|
796
810
|
session_id_hex=self.get_session_id_hex(),
|
|
797
811
|
)
|
|
798
812
|
|
|
@@ -805,6 +819,7 @@ class Connection:
|
|
|
805
819
|
raise NotSupportedError(
|
|
806
820
|
f"Setting transaction isolation level '{level}' is not supported. "
|
|
807
821
|
f"Only {TRANSACTION_ISOLATION_LEVEL_REPEATABLE_READ} is supported.",
|
|
822
|
+
host_url=self.session.host,
|
|
808
823
|
session_id_hex=self.get_session_id_hex(),
|
|
809
824
|
)
|
|
810
825
|
|
|
@@ -857,6 +872,7 @@ class Cursor:
|
|
|
857
872
|
else:
|
|
858
873
|
raise ProgrammingError(
|
|
859
874
|
"There is no active result set",
|
|
875
|
+
host_url=self.connection.session.host,
|
|
860
876
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
861
877
|
)
|
|
862
878
|
|
|
@@ -997,6 +1013,7 @@ class Cursor:
|
|
|
997
1013
|
if not self.open:
|
|
998
1014
|
raise InterfaceError(
|
|
999
1015
|
"Attempting operation on closed cursor",
|
|
1016
|
+
host_url=self.connection.session.host,
|
|
1000
1017
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1001
1018
|
)
|
|
1002
1019
|
|
|
@@ -1041,6 +1058,7 @@ class Cursor:
|
|
|
1041
1058
|
else:
|
|
1042
1059
|
raise ProgrammingError(
|
|
1043
1060
|
"You must provide at least one staging_allowed_local_path when initialising a connection to perform ingestion commands",
|
|
1061
|
+
host_url=self.connection.session.host,
|
|
1044
1062
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1045
1063
|
)
|
|
1046
1064
|
|
|
@@ -1067,6 +1085,7 @@ class Cursor:
|
|
|
1067
1085
|
if not allow_operation:
|
|
1068
1086
|
raise ProgrammingError(
|
|
1069
1087
|
"Local file operations are restricted to paths within the configured staging_allowed_local_path",
|
|
1088
|
+
host_url=self.connection.session.host,
|
|
1070
1089
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1071
1090
|
)
|
|
1072
1091
|
|
|
@@ -1095,6 +1114,7 @@ class Cursor:
|
|
|
1095
1114
|
raise ProgrammingError(
|
|
1096
1115
|
f"Operation {row.operation} is not supported. "
|
|
1097
1116
|
+ "Supported operations are GET, PUT, and REMOVE",
|
|
1117
|
+
host_url=self.connection.session.host,
|
|
1098
1118
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1099
1119
|
)
|
|
1100
1120
|
|
|
@@ -1110,6 +1130,7 @@ class Cursor:
|
|
|
1110
1130
|
if local_file is None:
|
|
1111
1131
|
raise ProgrammingError(
|
|
1112
1132
|
"Cannot perform PUT without specifying a local_file",
|
|
1133
|
+
host_url=self.connection.session.host,
|
|
1113
1134
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1114
1135
|
)
|
|
1115
1136
|
|
|
@@ -1135,6 +1156,7 @@ class Cursor:
|
|
|
1135
1156
|
error_text = r.data.decode() if r.data else ""
|
|
1136
1157
|
raise OperationalError(
|
|
1137
1158
|
f"Staging operation over HTTP was unsuccessful: {r.status}-{error_text}",
|
|
1159
|
+
host_url=self.connection.session.host,
|
|
1138
1160
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1139
1161
|
)
|
|
1140
1162
|
|
|
@@ -1166,6 +1188,7 @@ class Cursor:
|
|
|
1166
1188
|
if not stream:
|
|
1167
1189
|
raise ProgrammingError(
|
|
1168
1190
|
"No input stream provided for streaming operation",
|
|
1191
|
+
host_url=self.connection.session.host,
|
|
1169
1192
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1170
1193
|
)
|
|
1171
1194
|
|
|
@@ -1187,6 +1210,7 @@ class Cursor:
|
|
|
1187
1210
|
if local_file is None:
|
|
1188
1211
|
raise ProgrammingError(
|
|
1189
1212
|
"Cannot perform GET without specifying a local_file",
|
|
1213
|
+
host_url=self.connection.session.host,
|
|
1190
1214
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1191
1215
|
)
|
|
1192
1216
|
|
|
@@ -1201,6 +1225,7 @@ class Cursor:
|
|
|
1201
1225
|
error_text = r.data.decode() if r.data else ""
|
|
1202
1226
|
raise OperationalError(
|
|
1203
1227
|
f"Staging operation over HTTP was unsuccessful: {r.status}-{error_text}",
|
|
1228
|
+
host_url=self.connection.session.host,
|
|
1204
1229
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1205
1230
|
)
|
|
1206
1231
|
|
|
@@ -1222,6 +1247,7 @@ class Cursor:
|
|
|
1222
1247
|
error_text = r.data.decode() if r.data else ""
|
|
1223
1248
|
raise OperationalError(
|
|
1224
1249
|
f"Staging operation over HTTP was unsuccessful: {r.status}-{error_text}",
|
|
1250
|
+
host_url=self.connection.session.host,
|
|
1225
1251
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1226
1252
|
)
|
|
1227
1253
|
|
|
@@ -1413,6 +1439,7 @@ class Cursor:
|
|
|
1413
1439
|
else:
|
|
1414
1440
|
raise OperationalError(
|
|
1415
1441
|
f"get_execution_result failed with Operation status {operation_state}",
|
|
1442
|
+
host_url=self.connection.session.host,
|
|
1416
1443
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1417
1444
|
)
|
|
1418
1445
|
|
|
@@ -1541,6 +1568,7 @@ class Cursor:
|
|
|
1541
1568
|
else:
|
|
1542
1569
|
raise ProgrammingError(
|
|
1543
1570
|
"There is no active result set",
|
|
1571
|
+
host_url=self.connection.session.host,
|
|
1544
1572
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1545
1573
|
)
|
|
1546
1574
|
|
|
@@ -1558,6 +1586,7 @@ class Cursor:
|
|
|
1558
1586
|
else:
|
|
1559
1587
|
raise ProgrammingError(
|
|
1560
1588
|
"There is no active result set",
|
|
1589
|
+
host_url=self.connection.session.host,
|
|
1561
1590
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1562
1591
|
)
|
|
1563
1592
|
|
|
@@ -1583,6 +1612,7 @@ class Cursor:
|
|
|
1583
1612
|
else:
|
|
1584
1613
|
raise ProgrammingError(
|
|
1585
1614
|
"There is no active result set",
|
|
1615
|
+
host_url=self.connection.session.host,
|
|
1586
1616
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1587
1617
|
)
|
|
1588
1618
|
|
|
@@ -1593,6 +1623,7 @@ class Cursor:
|
|
|
1593
1623
|
else:
|
|
1594
1624
|
raise ProgrammingError(
|
|
1595
1625
|
"There is no active result set",
|
|
1626
|
+
host_url=self.connection.session.host,
|
|
1596
1627
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1597
1628
|
)
|
|
1598
1629
|
|
|
@@ -1603,6 +1634,7 @@ class Cursor:
|
|
|
1603
1634
|
else:
|
|
1604
1635
|
raise ProgrammingError(
|
|
1605
1636
|
"There is no active result set",
|
|
1637
|
+
host_url=self.connection.session.host,
|
|
1606
1638
|
session_id_hex=self.connection.get_session_id_hex(),
|
|
1607
1639
|
)
|
|
1608
1640
|
|