Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/code-quality-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ jobs:

- name: Run tests
run: poetry run python -m pytest tests/unit
check-linting:
code-format-check:
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down Expand Up @@ -216,10 +216,10 @@ jobs:
- name: Install library
run: poetry install --no-interaction
#----------------------------------------------
# black the code
# Run Ruff format check
#----------------------------------------------
- name: Black
run: poetry run black --check src
- name: Ruff format check
run: poetry run ruff format --check

check-types:
runs-on: ubuntu-latest
Expand Down
1 change: 0 additions & 1 deletion examples/custom_cred_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
credentials_provider=creds,
) as connection:

for x in range(1, 5):
cursor = connection.cursor()
cursor.execute("SELECT 1+1")
Expand Down
1 change: 1 addition & 0 deletions examples/experimental/tests/test_sea_async_query.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test for SEA asynchronous query execution functionality.
"""

import os
import sys
import logging
Expand Down
1 change: 1 addition & 0 deletions examples/experimental/tests/test_sea_metadata.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test for SEA metadata functionality.
"""

import os
import sys
import logging
Expand Down
1 change: 1 addition & 0 deletions examples/experimental/tests/test_sea_session.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test for SEA session management functionality.
"""

import os
import sys
import logging
Expand Down
1 change: 1 addition & 0 deletions examples/experimental/tests/test_sea_sync_query.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test for SEA synchronous query execution functionality.
"""

import os
import sys
import logging
Expand Down
1 change: 0 additions & 1 deletion examples/insert_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

with connection.cursor() as cursor:
cursor.execute("CREATE TABLE IF NOT EXISTS squares (x int, x_squared int)")

Expand Down
1 change: 0 additions & 1 deletion examples/interactive_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
server_hostname=os.getenv("DATABRICKS_SERVER_HOSTNAME"),
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
) as connection:

for x in range(1, 100):
cursor = connection.cursor()
cursor.execute("SELECT 1+1")
Expand Down
1 change: 0 additions & 1 deletion examples/persistent_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def read(self, hostname: str) -> Optional[OAuthToken]:
auth_type="databricks-oauth",
experimental_oauth_persistence=DevOnlyFilePersistence("./sample.json"),
) as connection:

for x in range(1, 100):
cursor = connection.cursor()
cursor.execute("SELECT 1+1")
Expand Down
79 changes: 43 additions & 36 deletions examples/proxy_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,122 +20,128 @@

# Configure logging to see proxy activity
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

# Uncomment for detailed debugging (shows HTTP requests/responses)
# logging.getLogger("urllib3").setLevel(logging.DEBUG)
# logging.getLogger("urllib3.connectionpool").setLevel(logging.DEBUG)


def check_proxy_environment():
"""Check if proxy environment variables are configured."""
proxy_vars = ['HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy']
configured_proxies = {var: os.environ.get(var) for var in proxy_vars if os.environ.get(var)}

proxy_vars = ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"]
configured_proxies = {
var: os.environ.get(var) for var in proxy_vars if os.environ.get(var)
}

if configured_proxies:
print("✓ Proxy environment variables found:")
for var, value in configured_proxies.items():
# Hide credentials in output for security
safe_value = value.split('@')[-1] if '@' in value else value
safe_value = value.split("@")[-1] if "@" in value else value
print(f" {var}: {safe_value}")
return True
else:
print("⚠ No proxy environment variables found")
print(" Set HTTP_PROXY and/or HTTPS_PROXY if using a proxy")
return False


def test_connection(connection_params, test_name):
"""Test a database connection with given parameters."""
print(f"\n--- Testing {test_name} ---")

try:
with sql.connect(**connection_params) as connection:
print("✓ Successfully connected!")

with connection.cursor() as cursor:
# Test basic query
cursor.execute("SELECT current_user() as user, current_database() as database")
cursor.execute(
"SELECT current_user() as user, current_database() as database"
)
result = cursor.fetchone()
print(f"✓ Connected as user: {result.user}")
print(f"✓ Default database: {result.database}")

# Test a simple computation
cursor.execute("SELECT 1 + 1 as result")
result = cursor.fetchone()
print(f"✓ Query result: 1 + 1 = {result.result}")

return True

except Exception as e:
print(f"✗ Connection failed: {e}")
return False


def main():
print("Databricks SQL Connector - Proxy Authentication Examples")
print("=" * 60)

# Check proxy configuration
has_proxy = check_proxy_environment()

# Get Databricks connection parameters
server_hostname = os.environ.get('DATABRICKS_SERVER_HOSTNAME')
http_path = os.environ.get('DATABRICKS_HTTP_PATH')
access_token = os.environ.get('DATABRICKS_TOKEN')
server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME")
http_path = os.environ.get("DATABRICKS_HTTP_PATH")
access_token = os.environ.get("DATABRICKS_TOKEN")

if not all([server_hostname, http_path, access_token]):
print("\n✗ Missing required environment variables:")
print(" DATABRICKS_SERVER_HOSTNAME")
print(" DATABRICKS_HTTP_PATH")
print(" DATABRICKS_HTTP_PATH")
print(" DATABRICKS_TOKEN")
return 1

print(f"\nConnecting to: {server_hostname}")

# Base connection parameters
base_params = {
'server_hostname': server_hostname,
'http_path': http_path,
'access_token': access_token
"server_hostname": server_hostname,
"http_path": http_path,
"access_token": access_token,
}

success_count = 0
total_tests = 0

# Test 1: Default proxy behavior (no _proxy_auth_method specified)
# This uses basic auth if credentials are in proxy URL, otherwise no auth
print("\n" + "="*60)
print("\n" + "=" * 60)
print("Test 1: Default Proxy Behavior")
print("Uses basic authentication if credentials are in proxy URL")
total_tests += 1
if test_connection(base_params, "Default Proxy Behavior"):
success_count += 1

# Test 2: Explicit basic authentication
print("\n" + "="*60)
print("\n" + "=" * 60)
print("Test 2: Explicit Basic Authentication")
print("Explicitly requests basic authentication (same as default)")
total_tests += 1
basic_params = base_params.copy()
basic_params['_proxy_auth_method'] = 'basic'
basic_params["_proxy_auth_method"] = "basic"
if test_connection(basic_params, "Basic Proxy Authentication"):
success_count += 1

# Test 3: Kerberos/Negotiate authentication
print("\n" + "="*60)
print("\n" + "=" * 60)
print("Test 3: Kerberos/Negotiate Authentication")
print("Uses Kerberos tickets for proxy authentication")
print("Note: Requires valid Kerberos tickets (run 'kinit' first)")
total_tests += 1
kerberos_params = base_params.copy()
kerberos_params['_proxy_auth_method'] = 'negotiate'
kerberos_params["_proxy_auth_method"] = "negotiate"
if test_connection(kerberos_params, "Kerberos Proxy Authentication"):
success_count += 1

# Summary
print(f"\n{'='*60}")
print(f"\n{'=' * 60}")
print(f"Summary: {success_count}/{total_tests} tests passed")

if success_count == total_tests:
print("✓ All proxy authentication methods working!")
return 0
Expand All @@ -149,5 +155,6 @@ def main():
print("Consider checking your proxy configuration")
return 1


if __name__ == "__main__":
exit(main())
1 change: 0 additions & 1 deletion examples/query_async_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

with connection.cursor() as cursor:
long_running_query = """
SELECT COUNT(*) FROM RANGE(10000 * 16) x
Expand Down
1 change: 0 additions & 1 deletion examples/query_cancel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

with connection.cursor() as cursor:

def execute_really_long_query():
Expand Down
1 change: 0 additions & 1 deletion examples/query_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

with connection.cursor() as cursor:
cursor.execute("SELECT * FROM default.diamonds LIMIT 2")
result = cursor.fetchall()
Expand Down
9 changes: 4 additions & 5 deletions examples/query_tags_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
session_configuration={
'QUERY_TAGS': 'team:engineering,test:query-tags',
'ansi_mode': False
}
"QUERY_TAGS": "team:engineering,test:query-tags",
"ansi_mode": False,
},
) as connection:

with connection.cursor() as cursor:
cursor.execute("SELECT 1")
result = cursor.fetchone()
print(f" Result: {result[0]}")

print("\n=== Query Tags Example Complete ===")
print("\n=== Query Tags Example Complete ===")
1 change: 0 additions & 1 deletion examples/set_user_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
access_token=os.getenv("DATABRICKS_TOKEN"),
user_agent_entry="ExamplePartnerTag",
) as connection:

with connection.cursor() as cursor:
cursor.execute("SELECT * FROM default.diamonds LIMIT 2")
result = cursor.fetchall()
Expand Down
3 changes: 0 additions & 3 deletions examples/staging_ingestion.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
_complete_path = os.path.realpath(FILEPATH)

if not os.path.exists(_complete_path):

# It's easiest to save a file in the same directory as this script. But any path to a file will work.
raise Exception(
"You need to set FILEPATH in this script to a file that actually exists."
Expand All @@ -56,9 +55,7 @@
access_token=os.getenv("DATABRICKS_TOKEN"),
staging_allowed_local_path=staging_allowed_local_path,
) as connection:

with connection.cursor() as cursor:

# Ingestion commands are executed like any other SQL.
# Here's a sample PUT query. You can remove OVERWRITE at the end to avoid silently overwriting data.
query = f"PUT '{_complete_path}' INTO 'stage://tmp/{INGESTION_USER}/pysql_examples/demo.csv' OVERWRITE"
Expand Down
11 changes: 5 additions & 6 deletions examples/streaming_put.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

with connection.cursor() as cursor:
# Create a simple data stream
data = b"Hello, streaming world!"
stream = io.BytesIO(data)

# Get catalog, schema, and volume from environment variables
catalog = os.getenv("DATABRICKS_CATALOG")
schema = os.getenv("DATABRICKS_SCHEMA")
volume = os.getenv("DATABRICKS_VOLUME")

# Upload to Unity Catalog volume
cursor.execute(
f"PUT '__input_stream__' INTO '/Volumes/{catalog}/{schema}/{volume}/hello.txt' OVERWRITE",
input_stream=stream
input_stream=stream,
)
print("File uploaded successfully!")

print("File uploaded successfully!")
1 change: 0 additions & 1 deletion examples/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
http_path=os.getenv("DATABRICKS_HTTP_PATH"),
access_token=os.getenv("DATABRICKS_TOKEN"),
) as connection:

# Disable autocommit to use explicit transactions
connection.autocommit = False

Expand Down
1 change: 0 additions & 1 deletion examples/v3_retries_query_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
_retry_dangerous_codes=[502, 400],
_retry_max_redirects=2,
) as connection:

with connection.cursor() as cursor:
cursor.execute("SELECT * FROM default.diamonds LIMIT 2")
result = cursor.fetchall()
Expand Down
Loading
Loading