Skip to content

Commit

Permalink
add(bot,web_api): setup types stubs for some ignored libraries
Browse files Browse the repository at this point in the history
Added basic type stubs for some of the smaller libraries the bot and
web_api use.

Libraries with missing types that remain:
- structlog, waiting on the release of its typed api
- requests_async, need to convert to httpx which has types
- asyncio_redis, maybe write stubs, or use a different client
- django, stubs exist, last time we tried it, there were a number of
  false positives
- stripe, no types currently, could probably write some minimal stubs
  rel: stripe/stripe-python#650
  • Loading branch information
sbdchd committed Nov 12, 2020
1 parent 71cdc12 commit c9f9c5f
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 21 deletions.
2 changes: 1 addition & 1 deletion bot/kodiak/event_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ async def get_redis() -> asyncio_redis.Connection:

def compress_payload(data: dict) -> bytes:
cctx = zstd.ZstdCompressor()
return cast(bytes, cctx.compress(json.dumps(data).encode()))
return cctx.compress(json.dumps(data).encode())


async def handle_webhook_event(event_name: str, payload: dict) -> None:
Expand Down
8 changes: 2 additions & 6 deletions bot/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
python_version=3.7
platform=linux

mypy_path=./typings

# flake8-mypy expects the two following for sensible formatting
show_column_numbers=True

Expand Down Expand Up @@ -40,15 +42,9 @@ ignore_missing_imports=True
[mypy-structlog.*]
ignore_missing_imports=True

[mypy-rure.*]
ignore_missing_imports=True

[mypy-asyncio_redis.*]
ignore_missing_imports=True

[mypy-zstandard.*]
ignore_missing_imports=True

# https://pydantic-docs.helpmanual.io/mypy_plugin/#plugin-settings
[pydantic-mypy]
init_forbid_extra = True
Expand Down
12 changes: 12 additions & 0 deletions bot/typings/rure.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from re import Match, RegexFlag
from typing import AnyStr, Optional, Pattern, overload

_FlagsType = RegexFlag
@overload
def search(
pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...
) -> Optional[Match[AnyStr]]: ...
@overload
def search(
pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...
) -> Optional[Match[AnyStr]]: ...
2 changes: 2 additions & 0 deletions bot/typings/zstandard.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ZstdCompressor:
def compress(self, arg: object) -> bytes: ...
11 changes: 2 additions & 9 deletions web_api/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
python_version=3.7
platform=linux

mypy_path=./typings

# flake8-mypy expects the two following for sensible formatting
show_column_numbers=True

Expand Down Expand Up @@ -37,15 +39,6 @@ plugins = pydantic.mypy
[mypy-django.*]
ignore_missing_imports=True

[mypy-dj_database_url.*]
ignore_missing_imports=True

[mypy-zstandard.*]
ignore_missing_imports=True

[mypy-responses.*]
ignore_missing_imports=True

[mypy-stripe.*]
ignore_missing_imports=True

Expand Down
19 changes: 19 additions & 0 deletions web_api/typings/dj_database_url.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import Optional

from typing_extensions import TypedDict

class DBConfig(TypedDict):
NAME: str
USER: str
PASSWORD: str
HOST: str
PORT: str
CONN_MAX_AGE: int
ENGINE: str

def parse(
url: str,
engine: Optional[str] = None,
conn_max_age: int = 0,
ssl_require: bool = False,
) -> DBConfig: ...
22 changes: 22 additions & 0 deletions web_api/typings/responses.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from __future__ import annotations

from typing import Any, Mapping, Optional

from typing_extensions import Literal

class RequestsMock:
def __enter__(self) -> RequestsMock: ...
def __exit__(self, type: object, value: object, traceback: object) -> bool: ...
def add(
self,
method: Optional[Literal["GET", "POST"]] = None,
url: Optional[str] = None,
body: str = "",
adding_headers: Optional[Mapping[str, str]] = None,
json: Optional[Mapping[str, Any]] = None,
status: Optional[int] = None,
content_type: Optional[str] = None,
) -> None: ...

GET: Literal["GET"]
POST: Literal["POST"]
2 changes: 2 additions & 0 deletions web_api/typings/zstandard.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ZstdDecompressor:
def decompress(self, data: bytes) -> bytes: ...
10 changes: 5 additions & 5 deletions web_api/web_api/test_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
import json
import time
from typing import Any, Optional, Tuple, Type, Union, cast
from typing import Any, Iterator, Optional, Tuple, Type, Union, cast

import pytest
import responses
Expand Down Expand Up @@ -167,7 +167,7 @@ def create_stripe_customer(


@pytest.fixture
def mocked_responses() -> Any:
def mocked_responses() -> Iterator[responses.RequestsMock]:
with responses.RequestsMock() as rsps:
yield rsps

Expand Down Expand Up @@ -2322,7 +2322,7 @@ def test_oauth_login(client: Client, state_token: str) -> None:


@pytest.fixture
def successful_sync_accounts_response(mocked_responses: Any) -> None:
def successful_sync_accounts_response(mocked_responses: responses.RequestsMock) -> None:
mocked_responses.add(
responses.GET,
"https://api.github.com/user/installations",
Expand Down Expand Up @@ -2387,7 +2387,7 @@ def successful_sync_accounts_response(mocked_responses: Any) -> None:


@pytest.fixture
def successful_responses(mocked_responses: Any) -> None:
def successful_responses(mocked_responses: responses.RequestsMock) -> None:
mocked_responses.add(
responses.POST,
"https://github.com/login/oauth/access_token",
Expand Down Expand Up @@ -2508,7 +2508,7 @@ def test_oauth_complete_success_existing_account(


@pytest.fixture
def failing_sync_accounts_response(mocked_responses: Any) -> None:
def failing_sync_accounts_response(mocked_responses: responses.RequestsMock) -> None:
mocked_responses.add(
responses.GET,
"https://api.github.com/user/installations",
Expand Down

0 comments on commit c9f9c5f

Please sign in to comment.