Skip to content

Commit 766a7a5

Browse files
authored
Merge pull request #28 from underchemist/27_fix_mypy_errors
Resolve mypy errors
2 parents 5924ce9 + 2a6b57b commit 766a7a5

21 files changed

+70
-70
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ repos:
1616
rev: v0.910
1717
hooks:
1818
- id: mypy
19-
language_version: python
19+
language_version: python
20+
args: [--install-types, --non-interactive]

oaff/app/oaff/app/data/sources/common/data_source_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
class DataSourceManager(ABC):
88
@abstractmethod
9-
def get_data_sources() -> List[Type[DataSource]]:
9+
def get_data_sources(self) -> List[Type[DataSource]]:
1010
pass

oaff/app/oaff/app/data/sources/postgresql/stac_hybrid/postgresql_data_source.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from hashlib import sha256
33
from logging import getLogger
44
from os import path
5-
from typing import Any, Coroutine, Dict, Final, List, Type
5+
from typing import Any, Awaitable, Callable, Dict, Final, List, Type
66

77
# geoalchemy import required for sa.MetaData reflection, even though unused in module
88
import geoalchemy2 as ga # noqa: F401
@@ -51,7 +51,7 @@ class PostgresqlDataSource(DataSource):
5151
def __init__(
5252
self,
5353
connection_name: str,
54-
connection_tester: Coroutine[None, None, Database],
54+
connection_tester: Callable[[Database, str], Awaitable[None]],
5555
):
5656
super().__init__(f"{self.DATA_SOURCE_NAME}:{connection_name}")
5757
self.db = Database(settings.url(connection_name))
@@ -155,7 +155,7 @@ def get_if_available(
155155
async def get_feature_set_provider(
156156
self,
157157
layer: PostgresqlLayer,
158-
constraints: ItemConstraints = None,
158+
constraints: ItemConstraints,
159159
ast: Type[Node] = None,
160160
) -> Type[FeatureSetProvider]:
161161
filters = (
@@ -414,8 +414,8 @@ async def _get_table_temporal_extents( # noqa: C901
414414
self,
415415
table_models: Dict[str, sa.Table],
416416
table_temporal_fields: Dict[str, List[TemporalInstant]],
417-
) -> Dict[str, List[datetime]]:
418-
table_temporal_extents = {}
417+
) -> Dict[str, List[List[datetime]]]:
418+
table_temporal_extents: Dict[str, List[List[datetime]]] = {}
419419
for qualified_table_name, temporal_fields in table_temporal_fields.items():
420420
start = None
421421
end = None

oaff/app/oaff/app/gateway.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77
from oaff.app.request_handlers.collection_items import (
88
CollectionsItems as CollectionsItemsRequestHandler,
99
)
10-
from oaff.app.request_handlers.collections_list import (
11-
CollectionsList as CollectionsListRequestHandler,
12-
)
10+
from oaff.app.request_handlers.collections_list import CollectionsListRequestHandler
1311
from oaff.app.request_handlers.common.request_handler import RequestHandler
14-
from oaff.app.request_handlers.conformance import Conformance as ConformanceRequestHandler
12+
from oaff.app.request_handlers.conformance import ConformanceRequestHandler
1513
from oaff.app.request_handlers.feature import Feature as FeatureRequestHandler
16-
from oaff.app.request_handlers.landing_page import (
17-
LandingPage as LandingPageRequestHandler,
18-
)
14+
from oaff.app.request_handlers.landing_page import LandingPageRequestHandler
1915
from oaff.app.requests.common.request_type import RequestType
2016
from oaff.app.responses.response import Response
2117

oaff/app/oaff/app/request_handlers/collection_items.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime, tzinfo
2-
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
2+
from typing import Any, Callable, Dict, Optional, Tuple, Type, Union, cast
33

44
from pygeofilter.ast import (
55
And,
@@ -82,7 +82,7 @@ def _get_page_link_retriever(
8282

8383
frontend_config = get_frontend_configuration()
8484

85-
def retriever(total_count: int, result_count: int) -> List[Link]:
85+
def retriever(total_count: int, result_count: int) -> Dict[PageLinkRel, Link]:
8686
links = {}
8787
if request.offset > 0:
8888
links[PageLinkRel.PREV] = Link(
@@ -107,7 +107,7 @@ def _collect_ast(
107107
self,
108108
bbox: BBox,
109109
datetime: Any,
110-
) -> Type[Node]:
110+
) -> Optional[Type[Node]]:
111111
if bbox is None and datetime is None:
112112
return None
113113
else:
@@ -120,21 +120,23 @@ def _collect_ast(
120120

121121
async def _spatial_bounds_to_node(
122122
self,
123-
spatial_bounds: Optional[
124-
Union[
125-
Tuple[float, float, float, float],
126-
Tuple[float, float, float, float, float, float],
127-
]
123+
spatial_bounds: Union[
124+
Tuple[float, float, float, float],
125+
Tuple[float, float, float, float, float, float],
128126
],
129127
spatial_bounds_crs: str,
130128
data_source: DataSource,
131129
layer: Layer,
132130
) -> BBox:
133-
x_min, y_min, x_max, y_max = (
134-
spatial_bounds
135-
if len(spatial_bounds) == 4
136-
else (spatial_bounds[i] for i in [0, 1, 3, 4])
137-
)
131+
# recommended usage for Union of types
132+
# https://github.com/python/mypy/issues/1178#issuecomment-176185607
133+
if len(spatial_bounds) == 4:
134+
a, b, c, d = cast(Tuple[float, float, float, float], spatial_bounds)
135+
else:
136+
a, b, _, c, d, _ = cast(
137+
Tuple[float, float, float, float, float, float], spatial_bounds
138+
)
139+
x_min, y_min, x_max, y_max = (a, b, c, d)
138140
transformer = Transformer.from_crs(
139141
"EPSG:4326", # True until Features API spec part 2 is implemented
140142
f"{layer.geometry_crs_auth_name}:{layer.geometry_crs_auth_code}",
@@ -155,13 +157,13 @@ async def _datetime_to_node( # noqa: C901
155157
self,
156158
temporal_bounds: Union[Tuple[datetime], Tuple[datetime, datetime]],
157159
layer: Layer,
158-
) -> Type[Node]:
160+
) -> Optional[Type[Node]]:
159161
if len(list(filter(lambda bound: bound is not None, temporal_bounds))) == 0:
160162
return None
161163
nodes = []
162164
for data_field in layer.temporal_attributes:
163165
if len(temporal_bounds) == 2:
164-
query_start, query_end = temporal_bounds
166+
query_start, query_end = cast(Tuple[datetime, datetime], temporal_bounds)
165167
if data_field.__class__ is TemporalInstant:
166168
if query_start is not None and query_end is not None:
167169
nodes.append(
@@ -333,6 +335,6 @@ def _match_query_time_to_end_field(
333335
)
334336

335337
def _match_query_time_to(
336-
self, query_time: datetime, tz_aware: bool, tz: Type[tzinfo]
338+
self, query_time: datetime, tz_aware: bool, tz: tzinfo
337339
) -> datetime:
338340
return query_time if tz_aware else query_time.astimezone(tz).replace(tzinfo=None)

oaff/app/oaff/app/request_handlers/collections_list.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from oaff.app.configuration.data import get_layers
55
from oaff.app.request_handlers.common.request_handler import RequestHandler
6-
from oaff.app.requests.collections_list import CollectionsList
6+
from oaff.app.requests.collections_list import CollectionsList as CollectionsListRequest
77
from oaff.app.responses.models.collection import CollectionHtml, CollectionJson
88
from oaff.app.responses.models.collections import CollectionsHtml, CollectionsJson
99
from oaff.app.responses.response import Response
@@ -12,12 +12,12 @@
1212
LOGGER: Final = getLogger(__file__)
1313

1414

15-
class CollectionsList(RequestHandler):
15+
class CollectionsListRequestHandler(RequestHandler):
1616
@classmethod
1717
def type_name(cls) -> str:
18-
return CollectionsList.__name__
18+
return CollectionsListRequest.__name__
1919

20-
async def handle(self, request: CollectionsList) -> Type[Response]:
20+
async def handle(self, request: CollectionsListRequest) -> Type[Response]:
2121
format_links = self.get_links_for_self(request)
2222
if request.format == ResponseFormat.html:
2323
collections = [

oaff/app/oaff/app/request_handlers/conformance.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
from typing import Type
22

33
from oaff.app.request_handlers.common.request_handler import RequestHandler
4-
from oaff.app.requests.conformance import Conformance
4+
from oaff.app.requests.conformance import Conformance as ConformanceRequest
55
from oaff.app.responses.models.conformance import ConformanceHtml, ConformanceJson
66
from oaff.app.responses.response import Response
77
from oaff.app.responses.response_format import ResponseFormat
88

99

10-
class Conformance(RequestHandler):
10+
class ConformanceRequestHandler(RequestHandler):
1111
@classmethod
1212
def type_name(cls) -> str:
13-
return Conformance.__name__
13+
return ConformanceRequest.__name__
1414

15-
async def handle(self, request: Conformance) -> Type[Response]:
15+
async def handle(self, request: ConformanceRequest) -> Type[Response]:
1616
conform_list = [
1717
"http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/core",
1818
"http://www.opengis.net/spec/ogcapi-common-2/1.0/conf/collections",

oaff/app/oaff/app/request_handlers/landing_page.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from oaff.app.configuration.frontend_interface import get_frontend_configuration
44
from oaff.app.i18n.translations import gettext_for_locale
55
from oaff.app.request_handlers.common.request_handler import RequestHandler
6-
from oaff.app.requests.landing_page import LandingPage
6+
from oaff.app.requests.landing_page import LandingPage as LandingPageRequest
77
from oaff.app.responses.models.landing import LandingHtml, LandingJson
88
from oaff.app.responses.models.link import Link, LinkRel
99
from oaff.app.responses.response import Response
@@ -12,12 +12,12 @@
1212
from oaff.app.settings import OPENAPI_OGC_TYPE
1313

1414

15-
class LandingPage(RequestHandler):
15+
class LandingPageRequestHandler(RequestHandler):
1616
@classmethod
1717
def type_name(cls) -> str:
18-
return LandingPage.__name__
18+
return LandingPageRequest.__name__
1919

20-
async def handle(self, request: LandingPage) -> Type[Response]:
20+
async def handle(self, request: LandingPageRequest) -> Type[Response]:
2121
gettext = gettext_for_locale(request.locale)
2222
frontend = get_frontend_configuration()
2323
title = gettext("Features API Landing Page")

oaff/app/oaff/app/responses/response_format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from oaff.app.responses.response_type import ResponseType
44

55

6-
class ResponseFormat(dict, Enum):
6+
class ResponseFormat(dict, Enum): # type: ignore[misc]
77
html = {
88
ResponseType.DATA: "text/html",
99
ResponseType.METADATA: "text/html",

oaff/app/oaff/app/responses/templates/templates.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def get_rendered_html(template_name: str, data: object, locale: Locales) -> str:
1313
loader=PackageLoader("oaff.app", path.join("responses", "templates", "html")),
1414
autoescape=select_autoescape(["html"]),
1515
)
16-
env.install_gettext_translations(get_translations_for_locale(locale))
16+
env.install_gettext_translations(get_translations_for_locale(locale)) # type: ignore
1717
frontend_config = get_frontend_configuration()
1818
return env.get_template(f"{template_name}.jinja2").render(
1919
response=data,

oaff/fastapi/api/openapi/openapi.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from typing import Callable
2+
13
from fastapi.applications import FastAPI
24
from fastapi.requests import Request
35

46
from oaff.fastapi.api.openapi.vnd_response import VndResponse
57

68

7-
def get_openapi_handler(app: FastAPI) -> VndResponse:
9+
def get_openapi_handler(app: FastAPI) -> Callable[[Request], VndResponse]:
810
def handler(_: Request):
911
# OpenAPI spec must be modified because FastAPI doesn't support
1012
# encoding style: https://github.com/tiangolo/fastapi/issues/283

oaff/fastapi/api/routes/collections.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
from datetime import datetime
22
from logging import getLogger
3-
from typing import Final, Optional, Tuple, Union
3+
from typing import Final, Optional, Tuple, Union, cast
44
from urllib.parse import quote
55

66
import iso8601
77
import pytz
8-
from fastapi import APIRouter, HTTPException
8+
from fastapi import APIRouter, HTTPException, Query
99
from fastapi.param_functions import Depends
10-
from fastapi.params import Query
1110
from fastapi.requests import Request
1211

1312
from oaff.app.requests.collection import Collection as CollectionRequestType
1413
from oaff.app.requests.collection_items import (
1514
CollectionItems as CollectionItemsRequestType,
1615
)
17-
from oaff.app.requests.collections_list import (
18-
CollectionsList as CollectionsListRequestType,
19-
)
16+
from oaff.app.requests.collections_list import CollectionsList as CollectionsListRequest
2017
from oaff.app.requests.feature import Feature as FeatureRequestType
2118
from oaff.app.responses.response_type import ResponseType
2219
from oaff.fastapi.api import settings
@@ -42,7 +39,7 @@ async def get_collections_list(
4239
):
4340
enforce_strict(request)
4441
return await delegate(
45-
CollectionsListRequestType(
42+
CollectionsListRequest(
4643
type=ResponseType.METADATA,
4744
format=common_parameters.format,
4845
locale=common_parameters.locale,
@@ -216,7 +213,7 @@ def parse_datetime(datetime_str: str) -> datetime:
216213
raise HTTPException(
217214
status_code=400, detail="datetime start cannot be after end"
218215
)
219-
return tuple(result)
216+
return cast(Union[Tuple[datetime], Tuple[datetime, datetime]], tuple(result))
220217

221218

222219
def _get_safe_url(path_template: str, request: Request, root: str) -> str:

oaff/fastapi/api/routes/common/common_parameters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from re import compile, search, sub
2-
from typing import Final, Optional, Set
2+
from typing import Final, List, Optional
33

44
from fastapi import Header, Query
55
from fastapi.requests import Request
@@ -66,7 +66,7 @@ async def populate(
6666
)
6767

6868
@classmethod
69-
def _header_options_by_preference(cls, header_value: str) -> Set[str]:
69+
def _header_options_by_preference(cls, header_value: str) -> List[str]:
7070
options = list(
7171
filter(
7272
lambda option: len(option) > 0,

oaff/fastapi/api/routes/common/parameter_control.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from oaff.fastapi.api.routes.common.common_parameters import COMMON_QUERY_PARAMS
88

99

10-
def strict(request: Request, permitted: Optional[List[str]] = []) -> None:
10+
def strict(request: Request, permitted: Optional[List[str]] = None) -> None:
11+
permitted = list() if permitted is None else permitted
1112
excessive = set(request.query_params.keys()).difference(
1213
set(permitted + COMMON_QUERY_PARAMS)
1314
)

oaff/fastapi/api/routes/conformance.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from fastapi import APIRouter, Depends
55
from fastapi.requests import Request
66

7-
from oaff.app.requests.conformance import Conformance as ConformanceRequestType
7+
from oaff.app.requests.conformance import Conformance as ConformanceRequest
88
from oaff.app.responses.response_type import ResponseType
99
from oaff.fastapi.api import settings
1010
from oaff.fastapi.api.delegator import delegate, get_default_handler
@@ -24,7 +24,7 @@ async def root(
2424
):
2525
enforce_strict(request)
2626
return await delegate(
27-
ConformanceRequestType(
27+
ConformanceRequest(
2828
type=ResponseType.METADATA,
2929
format=common_parameters.format,
3030
url=str(request.url),

oaff/fastapi/api/routes/landing_page.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from fastapi import APIRouter, Depends
55
from fastapi.requests import Request
66

7-
from oaff.app.requests.landing_page import LandingPage as LandingPageRequestType
7+
from oaff.app.requests.landing_page import LandingPage as LandingPageRequest
88
from oaff.app.responses.response_type import ResponseType
99
from oaff.fastapi.api import settings
1010
from oaff.fastapi.api.delegator import delegate, get_default_handler
@@ -24,7 +24,7 @@ async def root(
2424
):
2525
enforce_strict(request)
2626
return await delegate(
27-
LandingPageRequestType(
27+
LandingPageRequest(
2828
type=ResponseType.METADATA,
2929
format=common_parameters.format,
3030
url=str(request.url),

oaff/fastapi/api/util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ def _change_page(url: str, forward: bool) -> str:
5757
for key, value in {
5858
**parameters,
5959
**{
60-
"offset": max(offset + limit * (1 if forward else -1), 0),
61-
"limit": limit,
60+
"offset": str(max(offset + limit * (1 if forward else -1), 0)),
61+
"limit": str(limit),
6262
},
6363
}.items()
6464
]

oaff/fastapi/gunicorn/gunicorn.conf.py

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

33
cpu_limit = os.environ.get("API_CPU_LIMIT")
44
if cpu_limit is None:
5-
num_avail_cpus = len(os.sched_getaffinity(0))
5+
num_avail_cpus = len(os.sched_getaffinity(0)) # type: ignore[attr-defined]
66
else:
77
try:
88
num_avail_cpus = int(cpu_limit)

0 commit comments

Comments
 (0)