Skip to content

Commit b636925

Browse files
authored
Add pyright type checking to ci (developmentseed#388)
* Add pyright to ci * progress fixing ci * skip fsspec typing * type checks * fix from_url typing
1 parent 1f7352d commit b636925

File tree

10 files changed

+123
-19
lines changed

10 files changed

+123
-19
lines changed

.github/workflows/test-python.yml

+6
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,9 @@ jobs:
7474
- name: Check docs
7575
if: "${{ matrix.python-version == 3.11 }}"
7676
run: uv run mkdocs build --strict
77+
78+
- name: Add venv to PATH (for pyright action)
79+
run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
80+
81+
- name: Run pyright
82+
uses: jakebailey/pyright-action@v2

obstore/python/obstore/_store/__init__.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def from_url(
6565
**kwargs: Unpack[AzureConfig],
6666
) -> ObjectStore: ...
6767
@overload
68-
def from_url(
68+
def from_url( # type: ignore reportOverlappingOverload
6969
url: str,
7070
*,
7171
config: None = None,

obstore/python/obstore/fsspec.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,21 @@ def __init__(
161161
batch_size: int | None = None,
162162
**kwargs: Unpack[AzureConfig],
163163
) -> None: ...
164+
@overload
165+
def __init__(
166+
self,
167+
protocol: Literal["file"],
168+
*args: Any,
169+
config: None = None,
170+
client_options: None = None,
171+
retry_config: None = None,
172+
asynchronous: bool = False,
173+
max_cache_size: int = 10,
174+
loop: Any = None,
175+
batch_size: int | None = None,
176+
automatic_cleanup: bool = False,
177+
mkdir: bool = False,
178+
) -> None: ...
164179
def __init__( # noqa: PLR0913
165180
self,
166181
protocol: SUPPORTED_PROTOCOLS_T | str | None = None,
@@ -355,7 +370,7 @@ async def _cat_file(
355370
range_bytes = await obs.get_range_async(store, path, start=start, end=end)
356371
return range_bytes.to_bytes()
357372

358-
async def _cat(
373+
async def _cat( # type: ignore (fsspec has bad typing)
359374
self,
360375
path: str,
361376
recursive: bool = False,
@@ -373,15 +388,15 @@ async def _cat(
373388
raise FileNotFoundError(err_msg)
374389

375390
# Call the original _cat only on files
376-
return await super()._cat(
391+
return await super()._cat( # type: ignore (fsspec has bad typing)
377392
files,
378393
recursive=False,
379394
on_error=on_error,
380395
batch_size=batch_size,
381396
**_kwargs,
382397
)
383398

384-
async def _cat_ranges( # noqa: PLR0913
399+
async def _cat_ranges( # noqa: PLR0913 # type: ignore (fsspec has bad typing)
385400
self,
386401
paths: list[str],
387402
starts: list[int] | int,

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dev-dependencies = [
1313
"arro3-core>=0.4.2",
1414
"azure-identity>=1.21.0",
1515
"boto3>=1.35.38",
16+
"fastapi>=0.115.12", # used in example but added here for pyright CI
1617
"fsspec>=2024.10.0",
1718
"google-auth>=2.38.0",
1819
"griffe-inherited-docstrings>=1.0.1",
@@ -34,7 +35,9 @@ dev-dependencies = [
3435
"pystac>=1.10.1",
3536
"pytest-asyncio>=0.24.0",
3637
"pytest>=8.3.3",
38+
"python-dotenv>=1.0.1",
3739
"ruff>=0.11.0",
40+
"tqdm>=4.67.1", # used in example but added here for pyright CI
3841
"types-boto3[sts]>=1.36.23",
3942
]
4043
constraint-dependencies = [

tests/conftest.py

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

55
import boto3
66
import pytest
7-
import urllib3
7+
import requests
88
from botocore import UNSIGNED
99
from botocore.client import Config
1010
from moto.moto_server.threaded_moto_server import ThreadedMotoServer
@@ -27,7 +27,9 @@ def moto_server_uri():
2727
if hasattr(server, "get_host_and_port"):
2828
host, port = server.get_host_and_port()
2929
else:
30-
host, port = server._server.server_address
30+
s = server._server
31+
assert s is not None
32+
host, port = s.server_address
3133
uri = f"http://{host}:{port}"
3234
yield uri
3335
server.stop()
@@ -44,7 +46,7 @@ def s3(moto_server_uri: str):
4446
client.create_bucket(Bucket=TEST_BUCKET_NAME, ACL="public-read")
4547
client.put_object(Bucket=TEST_BUCKET_NAME, Key="afile", Body=b"hello world")
4648
yield moto_server_uri
47-
urllib3.request(method="post", url=f"{moto_server_uri}/moto-api/reset")
49+
requests.post(f"{moto_server_uri}/moto-api/reset", timeout=30)
4850

4951

5052
@pytest.fixture

tests/store/test_azure.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
def test_overlapping_config_keys():
88
with pytest.raises(BaseError, match="Duplicate key"):
9-
AzureStore(azure_container_name="test", AZURE_CONTAINER_NAME="test")
9+
AzureStore(container_name="test", AZURE_CONTAINER_NAME="test") # type: ignore intentional test
1010

1111
with pytest.raises(BaseError, match="Duplicate key"):
1212
AzureStore(
13-
config={"azure_container_name": "test", "AZURE_CONTAINER_NAME": "test"},
13+
config={"azure_container_name": "test", "AZURE_CONTAINER_NAME": "test"}, # type: ignore (intentional test)
1414
)
1515

1616

tests/store/test_from_url.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_memory():
1717
_store = from_url(url)
1818

1919
with pytest.raises(BaseError):
20-
from_url(url, aws_access_key_id="test")
20+
from_url(url, access_key_id="test")
2121

2222

2323
def test_s3_params():
@@ -28,7 +28,7 @@ def test_s3_params():
2828
)
2929

3030
with pytest.raises(UnknownConfigurationKeyError):
31-
from_url("s3://bucket/path", azure_authority_id="")
31+
from_url("s3://bucket/path", tenant_id="")
3232

3333

3434
def test_gcs_params():
@@ -38,20 +38,20 @@ def test_gcs_params():
3838
from_url("gs://test.example.com/path")
3939

4040
with pytest.raises(UnknownConfigurationKeyError):
41-
from_url("gs://test.example.com/path", azure_authority_id="")
41+
from_url("gs://test.example.com/path", tenant_id="")
4242

4343

4444
def test_azure_params():
4545
url = "abfs://[email protected]/path"
46-
from_url(url, azure_skip_signature=True)
46+
from_url(url, skip_signature=True)
4747

4848
with pytest.raises(UnknownConfigurationKeyError):
49-
from_url(url, aws_bucket="test")
49+
from_url(url, bucket="test")
5050

5151

5252
def test_http():
5353
url = "https://mydomain/path"
5454
from_url(url)
5555

5656
with pytest.raises(BaseError):
57-
from_url(url, aws_bucket="test")
57+
from_url(url, bucket="test")

tests/store/test_gcs.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
def test_overlapping_config_keys():
88
with pytest.raises(BaseError, match="Duplicate key"):
9-
GCSStore(google_bucket="bucket", GOOGLE_BUCKET="bucket")
9+
GCSStore(google_bucket="bucket", GOOGLE_BUCKET="bucket") # type: ignore intentional test
1010

1111
with pytest.raises(BaseError, match="Duplicate key"):
12-
GCSStore(config={"google_bucket": "test", "GOOGLE_BUCKET": "test"})
12+
GCSStore(config={"google_bucket": "test", "GOOGLE_BUCKET": "test"}) # type: ignore intentional test
1313

1414

1515
def test_eq():

tests/test_fsspec.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_register():
5959
)
6060

6161
# Ensure a new instance of the registered store can be created
62-
fs_instance = fs_class()
62+
fs_instance = fs_class("s3")
6363
assert isinstance(
6464
fs_instance,
6565
FsspecStore,
@@ -300,7 +300,7 @@ def test_put_files(fs: FsspecStore, tmp_path: Path):
300300

301301
# Verify file upload
302302
assert remote_file_path in fs.ls(f"{TEST_BUCKET_NAME}", detail=False)
303-
assert fs.cat(remote_file_path)[remote_file_path] == test_data.encode()
303+
assert fs.cat(remote_file_path)[remote_file_path] == test_data.encode() # type: ignore (fsspec)
304304

305305
# Cleanup remote file
306306
fs.rm(remote_file_path)

uv.lock

+78
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)