Skip to content

Commit 401d633

Browse files
boardwalk (bug): add model field annotations (#60)
Missing annotations lead to runtime errors from Pydantic; also bump Pydantic to v2.
1 parent e2231d7 commit 401d633

File tree

5 files changed

+20
-14
lines changed

5 files changed

+20
-14
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.8.14
1+
0.8.15

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ ansible-runner >=2.3.0
33
click >=8.1.3
44
cryptography >=38.0.3
55
email-validator >=1.3.0 # Required by pydantic to validate emails using EmailStr
6-
pydantic >=1.1.275
6+
pydantic >=2.4.2
77
tornado >=6.2

src/boardwalk/host.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ class Host(BaseModel, extra=Extra.forbid):
2828
ansible_facts: dict[str, Any]
2929
name: str
3030
meta: dict[str, str | int | bool] = {}
31-
remote_mutex_path = "/opt/boardwalk.mutex"
32-
remote_alert_msg = "ALERT: Boardwalk is running a workflow against this host. Services may be interrupted"
33-
remote_alert_string_formatted = f"$(tput -T xterm bold)$(tput -T xterm setaf 1)'{remote_alert_msg}'$(tput -T xterm sgr0)"
34-
remote_alert_motd = f"#!/bin/sh\necho {remote_alert_string_formatted}"
35-
remote_alert_motd_path = "/etc/update-motd.d/99-boardwalk-alert"
36-
remote_alert_wall_cmd = f"wall {remote_alert_string_formatted}"
31+
remote_mutex_path: str = "/opt/boardwalk.mutex"
32+
remote_alert_msg: str = "ALERT: Boardwalk is running a workflow against this host. Services may be interrupted"
33+
remote_alert_string_formatted: str = f"$(tput -T xterm bold)$(tput -T xterm setaf 1)'{remote_alert_msg}'$(tput -T xterm sgr0)"
34+
remote_alert_motd: str = f"#!/bin/sh\necho {remote_alert_string_formatted}"
35+
remote_alert_motd_path: str = "/etc/update-motd.d/99-boardwalk-alert"
36+
remote_alert_wall_cmd: str = f"wall {remote_alert_string_formatted}"
3737

3838
def ansible_run(
3939
self,

src/boardwalkd/protocol.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from pathlib import Path
1616
from urllib.parse import urljoin, urlparse
1717

18-
from pydantic import BaseModel, Extra, validator
18+
from pydantic import BaseModel, Extra, field_validator
1919
from tornado.httpclient import (
2020
HTTPClient,
2121
HTTPClientError,
@@ -64,7 +64,8 @@ def __init__(self, **kwargs: str):
6464
if not self.create_time:
6565
self.create_time: datetime | None = datetime.utcnow()
6666

67-
@validator("severity")
67+
@field_validator("severity")
68+
@classmethod
6869
def severity_level(cls, v: str):
6970
if v not in ["info", "success", "error"]:
7071
raise ValueError(f"invalid severity level")

src/boardwalkd/state.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from datetime import datetime
77
from pathlib import Path
88

9-
from pydantic import BaseModel, EmailStr, Extra, validator
9+
from pydantic import BaseModel, EmailStr, Extra, field_validator
1010

1111
from boardwalkd.protocol import WorkspaceDetails, WorkspaceEvent, WorkspaceSemaphores
1212

@@ -27,7 +27,8 @@ class User(StateBaseModel):
2727
email: EmailStr
2828
roles: set[str] = {"default"}
2929

30-
@validator("roles")
30+
@field_validator("roles")
31+
@classmethod
3132
def validate_roles(cls, input_roles: set[str]):
3233
for role in input_roles:
3334
if role not in valid_user_roles:
@@ -46,15 +47,19 @@ class WorkspaceState(StateBaseModel):
4647
events: deque[WorkspaceEvent] = deque([], maxlen=_max_workspace_events)
4748
semaphores: WorkspaceSemaphores = WorkspaceSemaphores()
4849

49-
@validator("events")
50+
@field_validator("events")
51+
@classmethod
5052
def validate_events(
5153
cls, input_events: deque[WorkspaceEvent]
5254
) -> deque[WorkspaceEvent]:
5355
"""
5456
Pydantic won't persist the maxlen argument for deque when cold loading
5557
from the statefile. This forces events to always be returned with maxlen
5658
"""
57-
return deque(input_events, maxlen=cls._max_workspace_events)
59+
# TODO: Figure out how to access the value here without using `.default` and needing
60+
# to ignore type errors; how do you extract an int from a ModelPrivateAttr?
61+
_max_events = cls._max_workspace_events.default # type: ignore
62+
return deque(input_events, maxlen=_max_events)
5863

5964

6065
class State(StateBaseModel):

0 commit comments

Comments
 (0)