Skip to content

Commit 7b1d9f0

Browse files
authored
Test Python 3.9 and 3.10 on CI; Apply fixes (#372)
* Expand Python versions on CI * Guard typing imports * Runtime fixes * fix import * fix get_ranges * skip some tests on 3.9
1 parent b351311 commit 7b1d9f0

19 files changed

+1047
-73
lines changed

.github/workflows/test-python.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
strategy:
4545
fail-fast: true
4646
matrix:
47-
python-version: ["3.11", "3.12"]
47+
python-version: ["3.9", "3.10", "3.11", "3.12"]
4848
steps:
4949
- uses: actions/checkout@v4
5050

obstore/python/obstore/_attributes.pyi

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
from typing import Literal, TypeAlias
1+
import sys
2+
from typing import Literal
3+
4+
if sys.version_info >= (3, 10):
5+
from typing import TypeAlias
6+
else:
7+
from typing_extensions import TypeAlias
28

39
Attribute: TypeAlias = (
410
Literal[

obstore/python/obstore/_list.pyi

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
# ruff: noqa: A001, UP006, UP035
22

3+
import sys
34
from datetime import datetime
4-
from typing import Generic, List, Literal, Self, TypedDict, TypeVar, overload
5+
from typing import Generic, List, Literal, TypedDict, TypeVar, overload
56

67
from arro3.core import RecordBatch, Table
78

89
from ._store import ObjectStore
910

11+
if sys.version_info >= (3, 11):
12+
from typing import Self
13+
else:
14+
from typing_extensions import Self
15+
1016
class ObjectMeta(TypedDict):
1117
"""The metadata that describes an object."""
1218

obstore/python/obstore/_put.pyi

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import sys
22
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
33
from pathlib import Path
4-
from typing import IO, Literal, TypeAlias, TypedDict
4+
from typing import IO, Literal, TypedDict
55

66
from ._attributes import Attributes
77
from .store import ObjectStore
88

9+
if sys.version_info >= (3, 10):
10+
from typing import TypeAlias
11+
else:
12+
from typing_extensions import TypeAlias
13+
914
if sys.version_info >= (3, 12):
1015
from collections.abc import Buffer
1116
else:

obstore/python/obstore/_sign.pyi

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import sys
12
from collections.abc import Sequence
23
from datetime import timedelta
3-
from typing import Literal, TypeAlias, overload
4+
from typing import Literal, overload
45

56
from .store import AzureStore, GCSStore, S3Store
67

8+
if sys.version_info >= (3, 10):
9+
from typing import TypeAlias
10+
else:
11+
from typing_extensions import TypeAlias
12+
713
HTTP_METHOD: TypeAlias = Literal[
814
"GET",
915
"PUT",

obstore/python/obstore/_store/__init__.pyi

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# TODO: move to reusable types package
2+
import sys
23
from collections.abc import Callable
34
from pathlib import Path
4-
from typing import Any, Self, TypeAlias, Unpack, overload
5+
from typing import Any, overload
56

67
from ._aws import S3Config as S3Config
78
from ._aws import S3Credential as S3Credential
@@ -23,6 +24,16 @@ from ._http import HTTPStore as HTTPStore
2324
from ._retry import BackoffConfig as BackoffConfig
2425
from ._retry import RetryConfig as RetryConfig
2526

27+
if sys.version_info >= (3, 10):
28+
from typing import TypeAlias
29+
else:
30+
from typing_extensions import TypeAlias
31+
32+
if sys.version_info >= (3, 11):
33+
from typing import Self, Unpack
34+
else:
35+
from typing_extensions import Self, Unpack
36+
2637
@overload
2738
def from_url(
2839
url: str,

obstore/python/obstore/_store/_aws.pyi

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1+
import sys
12
from collections.abc import Coroutine
23
from datetime import datetime
3-
from typing import (
4-
Any,
5-
Literal,
6-
NotRequired,
7-
Protocol,
8-
Self,
9-
TypeAlias,
10-
TypedDict,
11-
Unpack,
12-
)
4+
from typing import Any, Literal, Protocol, TypedDict
135

146
from ._client import ClientConfig
157
from ._retry import RetryConfig
168

9+
if sys.version_info >= (3, 10):
10+
from typing import TypeAlias
11+
else:
12+
from typing_extensions import TypeAlias
13+
14+
if sys.version_info >= (3, 11):
15+
from typing import NotRequired, Self, Unpack
16+
else:
17+
from typing_extensions import NotRequired, Self, Unpack
18+
1719
# To update s3 region list:
1820
# import pandas as pd # noqa: ERA001
1921
# url = "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html" # noqa: ERA001

obstore/python/obstore/_store/_azure.pyi

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
import sys
12
from collections.abc import Coroutine
23
from datetime import datetime
3-
from typing import Any, Protocol, Self, TypeAlias, TypedDict, Unpack
4+
from typing import Any, Protocol, TypedDict
45

56
from ._client import ClientConfig
67
from ._retry import RetryConfig
78

9+
if sys.version_info >= (3, 10):
10+
from typing import TypeAlias
11+
else:
12+
from typing_extensions import TypeAlias
13+
14+
if sys.version_info >= (3, 11):
15+
from typing import Self, Unpack
16+
else:
17+
from typing_extensions import Self, Unpack
18+
819
class AzureConfig(TypedDict, total=False):
920
"""Configuration parameters for AzureStore.
1021

obstore/python/obstore/_store/_gcs.pyi

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
import sys
12
from collections.abc import Coroutine
23
from datetime import datetime
3-
from typing import Any, Protocol, Self, TypedDict, Unpack
4+
from typing import Any, Protocol, TypedDict
45

56
from ._client import ClientConfig
67
from ._retry import RetryConfig
78

9+
if sys.version_info >= (3, 11):
10+
from typing import Self, Unpack
11+
else:
12+
from typing_extensions import Self, Unpack
13+
814
class GCSConfig(TypedDict, total=False):
915
"""Configuration parameters for GCSStore.
1016

obstore/python/obstore/_store/_http.pyi

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
from typing import Self
1+
import sys
22

33
from ._client import ClientConfig
44
from ._retry import RetryConfig
55

6+
if sys.version_info >= (3, 11):
7+
from typing import Self
8+
else:
9+
from typing_extensions import Self
10+
611
class HTTPStore:
712
"""Configure a connection to a generic HTTP server."""
813

obstore/python/obstore/auth/boto3.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@
22

33
from __future__ import annotations
44

5-
from datetime import UTC, datetime, timedelta
6-
from typing import TYPE_CHECKING, NotRequired, TypedDict, Unpack
5+
from datetime import datetime, timedelta, timezone
6+
from typing import TYPE_CHECKING, TypedDict
77

88
import boto3
99
import boto3.session
1010
import botocore.credentials
1111

1212
if TYPE_CHECKING:
13+
import sys
1314
from collections.abc import Sequence
1415

1516
import botocore.session
1617

1718
from obstore.store import S3Config, S3Credential
1819

20+
if sys.version_info >= (3, 11):
21+
from typing import NotRequired, Unpack
22+
else:
23+
from typing_extensions import NotRequired, Unpack
24+
1925

2026
class PolicyDescriptorTypeTypeDef(TypedDict): # noqa: D101
2127
arn: NotRequired[str]
@@ -97,7 +103,7 @@ def __init__(
97103

98104
def __call__(self) -> S3Credential:
99105
"""Fetch credentials."""
100-
expires_at = datetime.now(UTC) + self.ttl
106+
expires_at = datetime.now(timezone.utc) + self.ttl
101107
frozen_credentials = self.credentials.get_frozen_credentials()
102108
return {
103109
"access_key_id": frozen_credentials.access_key,

obstore/python/obstore/auth/google.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from datetime import UTC, datetime, timedelta
5+
from datetime import datetime, timedelta, timezone
66
from typing import TYPE_CHECKING, cast
77

88
import google.auth
@@ -156,4 +156,4 @@ def _replace_expiry_timezone_utc(expiry: datetime | None) -> datetime | None:
156156
if expiry is None:
157157
return None
158158

159-
return expiry.replace(tzinfo=UTC) if expiry.tzinfo is None else expiry
159+
return expiry.replace(tzinfo=timezone.utc) if expiry.tzinfo is None else expiry

obstore/python/obstore/fsspec.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from collections import defaultdict
3838
from functools import lru_cache
3939
from pathlib import Path
40-
from typing import TYPE_CHECKING, Any, Literal, Unpack, overload
40+
from typing import TYPE_CHECKING, Literal, overload
4141
from urllib.parse import urlparse
4242

4343
import fsspec.asyn
@@ -48,7 +48,9 @@
4848
from obstore.store import from_url
4949

5050
if TYPE_CHECKING:
51+
import sys
5152
from collections.abc import Coroutine, Iterable
53+
from typing import Any
5254

5355
from obstore import Attributes, Bytes, ReadableFile, WritableFile
5456
from obstore.store import (
@@ -60,6 +62,12 @@
6062
S3Config,
6163
)
6264

65+
if sys.version_info >= (3, 11):
66+
from typing import Unpack
67+
else:
68+
from typing_extensions import Unpack
69+
70+
6371
__all__ = [
6472
"BufferedFile",
6573
"FsspecStore",
@@ -391,9 +399,8 @@ async def _cat_ranges( # noqa: PLR0913
391399
raise ValueError
392400

393401
per_file_requests: dict[str, list[tuple[int, int, int]]] = defaultdict(list)
394-
for idx, (path, start, end) in enumerate(
395-
zip(paths, starts, ends, strict=False),
396-
):
402+
# When upgrading to Python 3.10, use strict=True
403+
for idx, (path, start, end) in enumerate(zip(paths, starts, ends)):
397404
per_file_requests[path].append((start, end, idx))
398405

399406
futs: list[Coroutine[Any, Any, list[Bytes]]] = []
@@ -409,13 +416,11 @@ async def _cat_ranges( # noqa: PLR0913
409416
result = await asyncio.gather(*futs)
410417

411418
output_buffers: list[bytes] = [b""] * len(paths)
412-
for per_file_request, buffers in zip(
413-
per_file_requests.items(),
414-
result,
415-
strict=True,
416-
):
419+
# When upgrading to Python 3.10, use strict=True
420+
for per_file_request, buffers in zip(per_file_requests.items(), result):
417421
path, ranges = per_file_request
418-
for buffer, ranges_ in zip(buffers, ranges, strict=True):
422+
# When upgrading to Python 3.10, use strict=True
423+
for buffer, ranges_ in zip(buffers, ranges):
419424
initial_index = ranges_[2]
420425
output_buffers[initial_index] = buffer.to_bytes()
421426

obstore/python/obstore/store.py

+20-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from __future__ import annotations
66

7-
from typing import TYPE_CHECKING, Any, Literal, TypeAlias, Unpack, overload
7+
from typing import TYPE_CHECKING, Union, overload
88

99
import obstore as obs
1010
from obstore._obstore import _store
@@ -22,7 +22,7 @@
2222
Sequence,
2323
)
2424
from pathlib import Path
25-
from typing import IO, Literal
25+
from typing import IO, Any, Literal
2626

2727
from arro3.core import RecordBatch, Table
2828

@@ -54,6 +54,16 @@
5454
S3CredentialProvider,
5555
)
5656

57+
if sys.version_info >= (3, 10):
58+
from typing import TypeAlias
59+
else:
60+
from typing_extensions import TypeAlias
61+
62+
if sys.version_info >= (3, 11):
63+
from typing import Unpack
64+
else:
65+
from typing_extensions import Unpack
66+
5767
if sys.version_info >= (3, 12):
5868
from collections.abc import Buffer
5969
else:
@@ -579,9 +589,14 @@ class S3Store(_ObjectStoreMixin, _store.S3Store):
579589
"""
580590

581591

582-
ObjectStore: TypeAlias = (
583-
AzureStore | GCSStore | HTTPStore | S3Store | LocalStore | MemoryStore
584-
)
592+
ObjectStore: TypeAlias = Union[
593+
AzureStore,
594+
GCSStore,
595+
HTTPStore,
596+
S3Store,
597+
LocalStore,
598+
MemoryStore,
599+
]
585600
"""All supported ObjectStore implementations."""
586601

587602

0 commit comments

Comments
 (0)