Skip to content

Commit a1aa5a7

Browse files
author
Jens Kürten
committed
add mypy
1 parent bff46c8 commit a1aa5a7

File tree

10 files changed

+39
-45
lines changed

10 files changed

+39
-45
lines changed

.pre-commit-config.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@ repos:
1111
args: [ --fix ]
1212
# Run the formatter.
1313
- id: ruff-format
14-
14+
- repo: https://github.com/pre-commit/mirrors-mypy
15+
rev: 'v1.15.0'
16+
hooks:
17+
- id: mypy
18+
additional_dependencies:
19+
[
20+
types-mock,
21+
types-requests,
22+
types-PyYAML
23+
]
1524
- repo: https://github.com/pre-commit/pre-commit-hooks
1625
rev: v4.4.0
1726
hooks:

csfunctions/actions/dummy.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,4 @@ class DummyAction(BaseAction):
88
Dummy Action, for unit testing
99
"""
1010

11-
def __init__(self, id: str, **kwargs): # pylint: disable=redefined-builtin
12-
super().__init__(name=ActionNames.DUMMY, id=id, data=kwargs["data"])
13-
14-
name: Literal[ActionNames.DUMMY]
11+
name: Literal[ActionNames.DUMMY] = ActionNames.DUMMY

csfunctions/handler.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def _get_function(function_name: str, function_dir: str) -> FunctionModel:
3131
config = _load_config(function_dir)
3232
func = next(func for func in config.functions if func.name == function_name)
3333
if not func:
34-
raise ValueError(f"Could not find function with name { function_name} in the environment.yaml.")
34+
raise ValueError(f"Could not find function with name {function_name} in the environment.yaml.")
3535
return func
3636

3737

@@ -81,24 +81,26 @@ def execute(function_name: str, request_body: str, function_dir: str = "src") ->
8181
try:
8282
request = Request(**json.loads(request_body))
8383
link_objects(request.event)
84+
8485
function_callback = get_function_callable(function_name, function_dir)
85-
service = Service(str(request.metadata.service_url), request.metadata.service_token)
86+
service = Service(
87+
str(request.metadata.service_url) if request.metadata.service_url else None, request.metadata.service_token
88+
)
8689

8790
response = function_callback(request.metadata, request.event, service)
8891

8992
if response is None:
9093
return ""
9194

92-
if isinstance(response, ActionUnion):
95+
if isinstance(response, ActionUnion): # type: ignore # MyPy doesn't like PEP604
9396
# wrap returned Actions into a WorkloadResponse
9497
response = WorkloadResponse(actions=[response])
95-
elif isinstance(response, list) and all(isinstance(o, ActionUnion) for o in response):
98+
elif isinstance(response, list) and all(isinstance(o, ActionUnion) for o in response): # type: ignore # MyPy doesn't like PEP604
9699
# wrap list of Actions into a WorkloadResponse
97100
response = WorkloadResponse(actions=response)
98101

99-
if not isinstance(
100-
response, ResponseUnion
101-
): # need to check for ResponseUnion instead of Response, because isinstance doesn't work with annotated unions
102+
if not isinstance(response, ResponseUnion): # type: ignore # MyPy doesn't like PEP604
103+
# need to check for ResponseUnion instead of Response, because isinstance doesn't work with annotated unions
102104
raise ValueError("Function needs to return a Response object or None.")
103105

104106
# make sure the event_id is filled out correctly

csfunctions/metadata.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,10 @@
11
from datetime import datetime
2+
from typing import Optional
23

34
from pydantic import AnyHttpUrl, BaseModel, Field
45

56

67
class MetaData(BaseModel):
7-
def __init__(
8-
self,
9-
app_lang: str,
10-
app_user: str,
11-
request_id: str,
12-
request_datetime: datetime,
13-
transaction_id: str,
14-
instance_url: str,
15-
db_service_url: str | None = None,
16-
**kwargs,
17-
):
18-
super().__init__(
19-
app_lang=app_lang,
20-
app_user=app_user,
21-
request_id=request_id,
22-
db_service_url=db_service_url,
23-
request_datetime=request_datetime,
24-
transaction_id=transaction_id,
25-
instance_url=instance_url,
26-
**kwargs,
27-
)
28-
298
app_lang: str = Field(..., description="ISO code of the session language that triggered the webhook.")
309
app_user: str = Field(..., description="User id of the user that triggered the webhook. (personalnummer)")
3110
request_id: str = Field(..., description="Unique identifier of this request.")
@@ -34,6 +13,6 @@ def __init__(
3413
request_datetime: datetime = Field(..., description="Time when the request was started.")
3514
transaction_id: str = Field(..., description="Unique identifier of the transaction.")
3615
instance_url: AnyHttpUrl = Field(..., description="URL to the instance where the webhook was triggered.")
37-
db_service_url: AnyHttpUrl | None = Field(
16+
db_service_url: Optional[AnyHttpUrl] = Field(
3817
None, description="URL to the DB Access Service responsible for the instance."
3918
)

csfunctions/objects/document.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,4 @@ class CADDocument(Document):
9898
Special Document type that contains a CAD-Model.
9999
"""
100100

101-
object_type: Literal[ObjectType.CAD_DOCUMENT] = ObjectType.CAD_DOCUMENT
101+
object_type: Literal[ObjectType.CAD_DOCUMENT] = ObjectType.CAD_DOCUMENT # type: ignore[assignment]

csfunctions/objects/workflow.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ class Workflow(BaseObject):
2525
global_briefcases: list[Briefcase] = Field([], exclude=True)
2626

2727
def link_objects(self, data: "EventData"):
28-
local_briefcases = getattr(data, "local_briefcases", None)
29-
global_briefcases = getattr(data, "local_briefcases", None)
28+
local_briefcases: list[Briefcase] | None = getattr(data, "local_briefcases", None)
29+
global_briefcases: list[Briefcase] | None = getattr(data, "local_briefcases", None)
3030

3131
if local_briefcases and self.local_briefcase_ids:
3232
self._link_local_briefcases(local_briefcases)
3333

3434
if global_briefcases and self.global_briefcase_ids:
35-
self._link_global_briefcases(local_briefcases)
35+
self._link_global_briefcases(global_briefcases)
3636

3737
def _link_local_briefcases(self, local_briefcases: list["Briefcase"]):
3838
for local_briefcase in local_briefcases:

csfunctions/service.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Optional
2+
13
import requests
24

35

@@ -6,7 +8,7 @@ class Service:
68
Provides access to services on the elements instance, e.g. generating numbers.
79
"""
810

9-
def __init__(self, service_url: str, service_token: str):
11+
def __init__(self, service_url: str | None, service_token: str | None):
1012
self.generator = NumberGeneratorService(service_url, service_token)
1113

1214

@@ -23,7 +25,7 @@ def __init__(self, service_url: str | None, service_token: str | None):
2325
self.service_url = service_url
2426
self.service_token = service_token
2527

26-
def request(self, endpoint: str, method: str = "GET", params: dict = None) -> dict | list:
28+
def request(self, endpoint: str, method: str = "GET", params: Optional[dict] = None) -> dict | list:
2729
"""
2830
Make a request to the access service.
2931
"""
@@ -35,7 +37,7 @@ def request(self, endpoint: str, method: str = "GET", params: dict = None) -> di
3537
headers = {"Authorization": f"Bearer {self.service_token}"}
3638
params = params or {}
3739
url = self.service_url.rstrip("/") + "/" + endpoint.lstrip("/")
38-
response = requests.request(method, url=url, params=params, headers=headers)
40+
response = requests.request(method, url=url, params=params, headers=headers, timeout=10)
3941

4042
if response.status_code == 401:
4143
raise Unauthorized
@@ -78,4 +80,8 @@ def get_numbers(self, name: str, count: int) -> list[int]:
7880
"""
7981
params = {"name": name, "count": count}
8082
data = self.request(self.endpoint, params=params)
83+
if not isinstance(data, dict):
84+
raise ValueError(f"Access service returned invalid data. Expected dict, got {type(data)}")
85+
if "numbers" not in data:
86+
raise ValueError(f"Access service returned invalid data. Expected 'numbers' key, got {data.keys()}")
8187
return data["numbers"]

tests/test_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class TestNumberGeneratorService(TestCase):
1010
endpoint = "numgen"
1111
service_url = "https://some_service_url"
1212
service_token = "some_service_token" # nosec
13-
service = None
13+
service: Service
1414

1515
@classmethod
1616
def setUpClass(cls) -> None:

tests/test_workloadresponse.py

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

88

99
class TestWorkloadResponse(TestCase):
10-
def test_discriminator(self):
10+
def test_discriminator(self) -> None:
1111
"""
1212
Test that the discriminator on action objects (and responses) works
1313
"""

tests/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from csfunctions import DataResponse, MetaData, Request, Service
44
from csfunctions.actions import AbortAndShowErrorAction
55
from csfunctions.events import DummyEvent
6+
from csfunctions.events.dummy import DummyEventData
67
from csfunctions.objects import Document, EngineeringChange, Part
78

89

@@ -149,7 +150,7 @@ def action_list_function(*args, **kwargs): # pylint: disable=unused-argument
149150
instance_url="https://instance.contact-cloud.com",
150151
service_url=None,
151152
),
152-
event=DummyEvent(event_id="42", data={"documents": [dummy_document], "parts": [dummy_part]}),
153+
event=DummyEvent(event_id="42", data=DummyEventData(documents=[dummy_document], parts=[dummy_part])),
153154
)
154155

155156

0 commit comments

Comments
 (0)