Skip to content

SNOW-2112225 move botocore and boto3 dependencies into an optional pack cloud-auth #2334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
- Add `bulk_upload_chunks` parameter to `write_pandas` function. Setting this parameter to True changes the behaviour of write_pandas function to first write all the data chunks to the local disk and then perform the wildcard upload of the chunks folder to the stage. In default behaviour the chunks are being saved, uploaded and deleted one by one.
- Added support for new authentication mechanism PAT with external session ID.
- Added `client_fetch_use_mp` parameter that enables multiprocessed fetching of result batches.
- Make botocore and boto3 an optional dependencies pack.

- v3.15.1(May 20, 2025)
- Added basic arrow support for Interval types.
Expand Down
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ python_requires = >=3.9
packages = find_namespace:
install_requires =
asn1crypto>0.24.0,<2.0.0
boto3>=1.24
botocore>=1.24
cffi>=1.9,<2.0.0
cryptography>=3.1.0,<=44.0.3
pyOpenSSL>=22.0.0,<26.0.0
Expand Down Expand Up @@ -97,3 +95,6 @@ pandas =
pyarrow<19.0.0
secure-local-storage =
keyring>=23.1.0,<26.0.0
aws =
boto3>=1.24
botocore>=1.24
38 changes: 38 additions & 0 deletions src/snowflake/connector/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ class MissingKeyring(MissingOptionalDependency):
_dep_name = "keyring"


class MissingBoto3(MissingOptionalDependency):
"""The class is specifically for boto3 optional dependency."""

_dep_name = "boto3"


class MissingBotoCore(MissingOptionalDependency):
"""The class is specifically for botocore optional dependency."""

_dep_name = "botocore"


ModuleLikeObject = Union[ModuleType, MissingOptionalDependency]


Expand Down Expand Up @@ -126,6 +138,32 @@ def _import_or_missing_keyring_option() -> tuple[ModuleLikeObject, bool]:
return MissingKeyring(), False


def _import_or_missing_botocore_option() -> tuple[ModuleLikeObject, bool]:
"""This function tries importing the following packages: botocore.

If available it returns botocore package with a flag of whether it was imported.
"""
try:
botocore = importlib.import_module("botocore")
return botocore, True
except ImportError:
return MissingBotoCore(), False


def _import_or_missing_boto3_option() -> tuple[ModuleLikeObject, bool]:
"""This function tries importing the following packages: boto3.

If available it returns boto3 package with a flag of whether it was imported.
"""
try:
boto3 = importlib.import_module("boto3")
return boto3, True
except ImportError:
return MissingBoto3(), False


# Create actual constants to be imported from this file
pandas, pyarrow, installed_pandas = _import_or_missing_pandas_option()
keyring, installed_keyring = _import_or_missing_keyring_option()
boto3, installed_boto3 = _import_or_missing_boto3_option()
botocore, installed_botocore = _import_or_missing_botocore_option()
20 changes: 16 additions & 4 deletions src/snowflake/connector/wif_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
from dataclasses import dataclass
from enum import Enum, unique

import boto3
import jwt
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.utils import InstanceMetadataRegionFetcher

from .options import boto3, installed_boto3, installed_botocore

if installed_botocore:
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.utils import InstanceMetadataRegionFetcher

from .errorcode import ER_WIF_CREDENTIALS_NOT_FOUND
from .errors import ProgrammingError
Expand Down Expand Up @@ -190,6 +193,15 @@ def create_aws_attestation() -> WorkloadIdentityAttestation | None:

If the application isn't running on AWS or no credentials were found, returns None.
"""
if not (installed_boto3 and installed_botocore):
logger.error("AWS attestation requires botocore and boto3 libraries")
_warn(
"Dependencies botocore and boto3 are not installed, cannot create AWS Workload Identity attestation."
"Please install these modules using the following command:\n"
" pip install snowflake-connector-python[aws]"
)
return None

aws_creds = boto3.session.Session().get_credentials()
if not aws_creds:
logger.debug("No AWS credentials were found.")
Expand Down
8 changes: 6 additions & 2 deletions test/csp_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
from urllib.parse import parse_qs, urlparse

import jwt
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials

from snowflake.connector.options import installed_botocore

if installed_botocore:
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials

from snowflake.connector.vendored.requests.exceptions import ConnectTimeout, HTTPError
from snowflake.connector.vendored.requests.models import Response
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extras =
development
pandas: pandas
sso: secure-local-storage
aws
package = wheel
setenv =
COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}/.coverage.{envname}}
Expand Down
Loading