Skip to content

Commit 50f4e19

Browse files
authored
feat: drop support for Python <=3.10 and require >=3.11 (#1485)
1 parent 5200d35 commit 50f4e19

13 files changed

Lines changed: 50 additions & 47 deletions

File tree

‎.github/workflows/tests.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
strategy:
3636
matrix:
3737
os: [macos-latest, windows-latest, ubuntu-latest]
38-
python-version: ["3.10", "3.14"]
38+
python-version: ["3.11", "3.14"]
3939
fail-fast: false
4040
permissions:
4141
contents: read
@@ -144,7 +144,7 @@ jobs:
144144
runs-on: ubuntu-latest
145145
strategy:
146146
matrix:
147-
python-version: ["3.10", "3.14"]
147+
python-version: ["3.11", "3.14"]
148148
fail-fast: false
149149
permissions:
150150
contents: read

‎google/cloud/sql/connector/client.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ async def _get_ephemeral(
285285
# google.auth library strips timezone info for backwards compatibality
286286
# reasons with Python 2. Add it back to allow timezone aware datetimes.
287287
# Ref: https://github.com/googleapis/google-auth-library-python/blob/49a5ff7411a2ae4d32a7d11700f9f961c55406a9/google/auth/_helpers.py#L93-L99
288-
token_expiration = token_expiration.replace(tzinfo=datetime.timezone.utc)
288+
token_expiration = token_expiration.replace(tzinfo=datetime.UTC)
289289

290290
expiration = min(expiration, token_expiration)
291291
return ephemeral_cert, expiration

‎google/cloud/sql/connector/connector.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@
1717
from __future__ import annotations
1818

1919
import asyncio
20+
from collections.abc import Callable
2021
from functools import partial
2122
import logging
2223
import os
2324
import socket
2425
from threading import Thread
2526
from types import TracebackType
26-
from typing import Any, Callable
27+
from typing import Any
2728

2829
import google.auth
2930
from google.auth.credentials import Credentials

‎google/cloud/sql/connector/instance.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import asyncio
2020
from datetime import datetime
2121
from datetime import timedelta
22-
from datetime import timezone
22+
from datetime import UTC
2323
import logging
2424

2525
from google.cloud.sql.connector.client import CloudSQLClient
@@ -221,7 +221,7 @@ async def _refresh_task(self: RefreshAheadCache, delay: int) -> ConnectionInfo:
221221
logger.debug(
222222
f"['{self._conn_name}']: Connection info refresh"
223223
" operation scheduled for "
224-
f"{(datetime.now(timezone.utc) + timedelta(seconds=delay)).isoformat(timespec='seconds')} "
224+
f"{(datetime.now(UTC) + timedelta(seconds=delay)).isoformat(timespec='seconds')} "
225225
f"(now + {timedelta(seconds=delay)})"
226226
)
227227
self._next = self._schedule_refresh(delay)

‎google/cloud/sql/connector/lazy.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import asyncio
1818
from datetime import datetime
1919
from datetime import timedelta
20-
from datetime import timezone
20+
from datetime import UTC
2121
import logging
2222

2323
from google.cloud.sql.connector.client import CloudSQLClient
@@ -121,7 +121,7 @@ async def connect_info(self) -> ConnectionInfo:
121121
if (
122122
self._cached
123123
and not self._needs_refresh
124-
and datetime.now(timezone.utc)
124+
and datetime.now(UTC)
125125
< (self._cached.expiration - timedelta(seconds=_refresh_buffer))
126126
):
127127
logger.debug(

‎google/cloud/sql/connector/monitored_cache.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
from __future__ import annotations
1616

1717
import asyncio
18+
from collections.abc import Callable
1819
import logging
1920
import ssl
20-
from typing import Any, Callable
21+
from typing import Any
2122

2223
import aiohttp
2324

‎google/cloud/sql/connector/refresh_utils.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
from __future__ import annotations
1818

1919
import asyncio
20+
from collections.abc import Callable
2021
import copy
2122
import datetime
2223
import logging
2324
import random
24-
from typing import Any, Callable
25+
from typing import Any
2526

2627
import aiohttp
2728
from google.auth.credentials import Credentials
@@ -52,7 +53,7 @@ def _seconds_until_refresh(
5253
"""
5354

5455
duration = int(
55-
(expiration - datetime.datetime.now(datetime.timezone.utc)).total_seconds()
56+
(expiration - datetime.datetime.now(datetime.UTC)).total_seconds()
5657
)
5758

5859
# if certificate duration is less than 1 hour
@@ -70,7 +71,7 @@ async def _is_valid(task: asyncio.Task) -> bool:
7071
try:
7172
metadata = await task
7273
# only valid if now is before the cert expires
73-
if datetime.datetime.now(datetime.timezone.utc) < metadata.expiration:
74+
if datetime.datetime.now(datetime.UTC) < metadata.expiration:
7475
return True
7576
except Exception: # noqa: BLE001
7677
# supress any errors from task

‎noxfile.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
LINT_PATHS = ["google", "tests", "noxfile.py"]
2323

24-
TEST_PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14"]
24+
TEST_PYTHON_VERSIONS = ["3.11", "3.12", "3.13", "3.14"]
2525

2626

2727
@nox.session

‎pyproject.toml‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ name = "cloud-sql-python-connector"
2222
authors = [{ name = "Google LLC", email = "googleapis-packages@google.com" }]
2323
license = "Apache-2.0"
2424
license-files = ["LICENSE"]
25-
requires-python = ">=3.9"
25+
requires-python = ">=3.11"
2626
readme = "README.md"
2727
classifiers = [
2828
# Should be one of:
@@ -33,11 +33,10 @@ classifiers = [
3333
"Intended Audience :: Developers",
3434
"Programming Language :: Python",
3535
"Programming Language :: Python :: 3",
36-
"Programming Language :: Python :: 3.9",
37-
"Programming Language :: Python :: 3.10",
3836
"Programming Language :: Python :: 3.11",
3937
"Programming Language :: Python :: 3.12",
4038
"Programming Language :: Python :: 3.13",
39+
"Programming Language :: Python :: 3.14",
4140
"Operating System :: OS Independent",
4241
]
4342
dependencies = [
@@ -77,7 +76,7 @@ version = { attr = "google.cloud.sql.connector.version.__version__" }
7776
include = ["google*"]
7877

7978
[tool.mypy]
80-
python_version = "3.9"
79+
python_version = "3.11"
8180
namespace_packages = true
8281
ignore_missing_imports = true
8382
warn_unused_configs = true

‎tests/unit/mocks.py‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818

1919
from __future__ import annotations
2020

21+
from collections.abc import Callable
2122
import datetime
2223
import json
2324
import ssl
24-
from typing import Any, Callable, Literal
25+
from typing import Any, Literal
2526

2627
from aiohttp import web
2728
from cryptography import x509
@@ -56,7 +57,7 @@ def __class__(self) -> Credentials:
5657
def refresh(self, _: Callable) -> None:
5758
"""Refreshes the access token."""
5859
self.token = "12345"
59-
self.expiry = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(
60+
self.expiry = datetime.datetime.now(datetime.UTC) + datetime.timedelta(
6061
minutes=60
6162
)
6263

@@ -70,7 +71,7 @@ def expired(self) -> bool:
7071
"""
7172
if self.expiry is None:
7273
return False
73-
return not self.expiry > datetime.datetime.now(datetime.timezone.utc)
74+
return not self.expiry > datetime.datetime.now(datetime.UTC)
7475

7576
@property
7677
def universe_domain(self) -> str:
@@ -94,11 +95,11 @@ def token_state(
9495
if self.expiry is None:
9596
return TokenState.FRESH
9697

97-
expired = datetime.datetime.now(datetime.timezone.utc) >= self.expiry
98+
expired = datetime.datetime.now(datetime.UTC) >= self.expiry
9899
if expired:
99100
return TokenState.INVALID
100101

101-
is_stale = datetime.datetime.now(datetime.timezone.utc) >= (
102+
is_stale = datetime.datetime.now(datetime.UTC) >= (
102103
self.expiry - _helpers.REFRESH_THRESHOLD
103104
)
104105
if is_stale:
@@ -117,9 +118,9 @@ def generate_cert(
117118
Generate a private key and cert object to be used in testing.
118119
"""
119120
if cert_before is None:
120-
cert_before = datetime.datetime.now(datetime.timezone.utc)
121+
cert_before = datetime.datetime.now(datetime.UTC)
121122
if cert_after is None:
122-
cert_after = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=1)
123+
cert_after = datetime.datetime.now(datetime.UTC) + datetime.timedelta(hours=1)
123124
# generate private key
124125
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
125126
common_name = f"{project}:{name}"
@@ -168,9 +169,9 @@ def client_key_signed_cert(
168169
Create a PEM encoded certificate that is signed by given public key.
169170
"""
170171
if cert_before is None:
171-
cert_before = datetime.datetime.now(datetime.timezone.utc)
172+
cert_before = datetime.datetime.now(datetime.UTC)
172173
if cert_expiration is None:
173-
cert_expiration = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=1)
174+
cert_expiration = datetime.datetime.now(datetime.UTC) + datetime.timedelta(hours=1)
174175
# configure cert subject
175176
subject = issuer = x509.Name(
176177
[
@@ -234,9 +235,9 @@ def __init__(
234235
cert_expiration: datetime.datetime | None = None,
235236
) -> None:
236237
if cert_before is None:
237-
cert_before = datetime.datetime.now(datetime.timezone.utc)
238+
cert_before = datetime.datetime.now(datetime.UTC)
238239
if cert_expiration is None:
239-
cert_expiration = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=1)
240+
cert_expiration = datetime.datetime.now(datetime.UTC) + datetime.timedelta(hours=1)
240241
if dns_names is None:
241242
dns_names = ["abcde.12345.us-central1.sql.goog"]
242243
if ip_addrs is None:

0 commit comments

Comments
 (0)