Skip to content

Commit 2a6ccb7

Browse files
authored
Fix #956: add default UTC timezone to queue items (#957)
1 parent 178aede commit 2a6ccb7

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

jbi/bugzilla/models.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
11
import datetime
22
import logging
3-
from typing import Optional, TypedDict
3+
from typing import Any, Optional, TypedDict
44
from urllib.parse import ParseResult, urlparse
55

6-
from pydantic import BaseModel, TypeAdapter
6+
from pydantic import (
7+
AwareDatetime,
8+
BaseModel,
9+
TypeAdapter,
10+
ValidationError,
11+
ValidationInfo,
12+
ValidatorFunctionWrapHandler,
13+
)
14+
from pydantic.functional_validators import WrapValidator
15+
from typing_extensions import Annotated
716

817
logger = logging.getLogger(__name__)
918
JIRA_HOSTNAMES = ("jira", "atlassian")
1019

1120
BugId = TypedDict("BugId", {"id": Optional[int]})
1221

1322

23+
def maybe_add_timezone(
24+
v: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo
25+
):
26+
if isinstance(v, str):
27+
try:
28+
return handler(v)
29+
except ValidationError:
30+
return handler(v + "+00:00")
31+
assert isinstance(v, datetime.datetime), "must be a datetime here"
32+
v = v.replace(tzinfo=datetime.timezone.utc)
33+
return v
34+
35+
36+
SmartAwareDatetime = Annotated[AwareDatetime, WrapValidator(maybe_add_timezone)]
37+
38+
1439
class WebhookUser(BaseModel, frozen=True):
1540
"""Bugzilla User Object"""
1641

@@ -31,7 +56,7 @@ class WebhookEvent(BaseModel, frozen=True):
3156
"""Bugzilla Event Object"""
3257

3358
action: str
34-
time: datetime.datetime
59+
time: SmartAwareDatetime
3560
user: Optional[WebhookUser] = None
3661
changes: Optional[list[WebhookEventChange]] = None
3762
target: Optional[str] = None
@@ -50,7 +75,7 @@ class WebhookComment(BaseModel, frozen=True):
5075
id: Optional[int] = None
5176
number: Optional[int] = None
5277
is_private: Optional[bool] = None
53-
creation_time: Optional[datetime.datetime] = None
78+
creation_time: Optional[SmartAwareDatetime] = None
5479

5580

5681
class Bug(BaseModel, frozen=True):

tests/unit/jira/test_queue.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
from datetime import datetime, timedelta
23

34
import pytest
@@ -207,6 +208,24 @@ async def test_get_invalid_json(backend: QueueBackend, queue_item_factory):
207208
await anext(items)
208209

209210

211+
@pytest.mark.asyncio
212+
async def test_get_missing_timezone(backend: QueueBackend, queue_item_factory):
213+
item = queue_item_factory.build(payload__bug__id=666)
214+
dump = item.model_dump()
215+
dump["payload"]["event"]["time"] = "2024-04-18T12:46:54"
216+
217+
queue_dir = backend.location / "666"
218+
queue_dir.mkdir()
219+
corrupt_file_path = queue_dir / f"{item.identifier}.json"
220+
corrupt_file_path.write_text(json.dumps(dump))
221+
222+
items = backend.get(666)
223+
item = await anext(items)
224+
225+
assert item.timestamp.tzname() == "UTC", "default timezone added"
226+
assert "2024-04-18T12:46:54Z" in item.model_dump_json(), "timezone put in dump"
227+
228+
210229
@pytest.mark.asyncio
211230
async def test_get_payload_doesnt_match_schema(
212231
backend: QueueBackend, queue_item_factory

0 commit comments

Comments
 (0)